[project @ 2001-03-13 14:58:25 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcClassDcl.lhs
index 0114a03..3994e93 100644 (file)
@@ -24,16 +24,16 @@ import RnHsSyn              ( RenamedTyClDecl,
                        )
 import TcHsSyn         ( TcMonoBinds )
 
-import Inst            ( InstOrigin(..), LIE, emptyLIE, plusLIE, plusLIEs, 
-                         newDicts, newMethod )
-import TcEnv           ( TcId, TcEnv, RecTcEnv, TyThingDetails(..), tcAddImportedIdInfo,
+import Inst            ( Inst, InstOrigin(..), LIE, emptyLIE, plusLIE, plusLIEs, 
+                         instToId, newDicts, newMethod )
+import TcEnv           ( RecTcEnv, TyThingDetails(..), tcAddImportedIdInfo,
                          tcLookupClass, tcExtendTyVarEnvForMeths, tcExtendGlobalTyVars,
                          tcExtendLocalValEnv, tcExtendTyVarEnv
                        )
 import TcBinds         ( tcBindWithSigs, tcSpecSigs )
-import TcMonoType      ( tcHsRecType, tcRecClassContext, checkSigTyVars, checkAmbiguity, sigCtxt, mkTcSig )
-import TcSimplify      ( tcSimplifyAndCheck, bindInstsOfLocalFuns )
-import TcType          ( TcType, TcTyVar, tcInstTyVars, zonkTcSigTyVars )
+import TcMonoType      ( tcHsRecType, tcRecTheta, checkSigTyVars, checkAmbiguity, sigCtxt, mkTcSig )
+import TcSimplify      ( tcSimplifyCheck, bindInstsOfLocalFuns )
+import TcType          ( TcType, TcTyVar, tcInstTyVars )
 import TcMonad
 import Generics                ( mkGenericRhs, validGenericMethodType )
 import PrelInfo                ( nO_METHOD_BINDING_ERROR_ID )
@@ -44,10 +44,10 @@ import DataCon              ( mkDataCon, notMarkedStrict )
 import Id              ( Id, idType, idName )
 import Module          ( Module )
 import Name            ( Name, NamedThing(..) )
-import Name            ( NameEnv, lookupNameEnv, emptyNameEnv, unitNameEnv, plusNameEnv, nameEnvElts )
+import NameEnv         ( NameEnv, lookupNameEnv, emptyNameEnv, unitNameEnv, plusNameEnv, nameEnvElts )
 import NameSet         ( emptyNameSet )
 import Outputable
-import Type            ( Type, ClassContext, mkTyVarTys, mkDictTys, mkClassPred,
+import Type            ( Type, ThetaType, mkTyVarTys, mkPredTys, mkClassPred,
                          splitTyConApp_maybe, isTyVarTy
                        )
 import Var             ( TyVar )
@@ -108,9 +108,12 @@ tcClassDecl1 is_rec rec_env
                         tcdSigs = class_sigs, tcdMeths = def_methods,
                         tcdSysNames = sys_names, tcdLoc = src_loc})
   =    -- CHECK ARITY 1 FOR HASKELL 1.4
-    doptsTc Opt_GlasgowExts                            `thenTc` \ glaExts ->
-    checkTc (glaExts || length tyvar_names == 1)
-           (classArityErr class_name)                  `thenTc_`
+    doptsTc Opt_GlasgowExts                            `thenTc` \ gla_ext_opt ->
+    let
+       gla_exts = gla_ext_opt || not (maybeToBool def_methods)
+               -- Accept extensions if gla_exts is on,
+               -- or if we're looking at an interface file decl
+    in         -- (in which case def_methods = Nothing
 
        -- LOOK THINGS UP IN THE ENVIRONMENT
     tcLookupClass class_name                           `thenTc` \ clas ->
@@ -124,14 +127,20 @@ tcClassDecl1 is_rec rec_env
 
        -- SOURCE-CODE CONSISTENCY CHECKS
     (case def_methods of
-       Nothing  -> returnTc Nothing    -- Not source
-       Just dms -> checkDefaultBinds clas op_names dms   `thenTc` \ dm_env ->
+       Nothing  ->     -- Not source
+                   returnTc Nothing    
+
+       Just dms ->     -- Source so do error checks
+                   checkTc (gla_exts || length tyvar_names == 1)
+                           (classArityErr class_name)                  `thenTc_`
+
+                   checkDefaultBinds clas op_names dms   `thenTc` \ dm_env ->
                    checkGenericClassIsUnary clas dm_env  `thenTc_`
                    returnTc (Just dm_env)
     )                                                     `thenTc` \ mb_dm_env ->
        
        -- CHECK THE CONTEXT
-    tcSuperClasses is_rec clas context sc_sel_names    `thenTc` \ (sc_theta, sc_sel_ids) ->
+    tcSuperClasses is_rec gla_exts clas context sc_sel_names   `thenTc` \ (sc_theta, sc_sel_ids) ->
 
        -- CHECK THE CLASS SIGNATURES,
     mapTc (tcClassSig is_rec rec_env clas tyvars mb_dm_env) op_sigs    `thenTc` \ sig_stuff ->
@@ -139,7 +148,7 @@ tcClassDecl1 is_rec rec_env
        -- MAKE THE CLASS DETAILS
     let
        (op_tys, op_items) = unzip sig_stuff
-        sc_tys            = mkDictTys sc_theta
+        sc_tys            = mkPredTys sc_theta
        dict_component_tys = sc_tys ++ op_tys
 
         dict_con = mkDataCon datacon_name
@@ -207,27 +216,23 @@ checkGenericClassIsUnary clas dm_env
 
 
 \begin{code}
-tcSuperClasses :: RecFlag -> Class
+tcSuperClasses :: RecFlag -> Bool -> Class
               -> RenamedContext        -- class context
               -> [Name]                -- Names for superclass selectors
-              -> TcM (ClassContext,    -- the superclass context
-                        [Id])          -- superclass selector Ids
+              -> TcM (ThetaType,       -- the superclass context
+                      [Id])            -- superclass selector Ids
 
-tcSuperClasses is_rec clas context sc_sel_names
-  =    -- Check the context.
+tcSuperClasses is_rec gla_exts clas context sc_sel_names
+  = ASSERT( length context == length sc_sel_names )
+       -- Check the context.
        -- The renamer has already checked that the context mentions
        -- only the type variable of the class decl.
 
        -- For std Haskell check that the context constrains only tyvars
-    doptsTc Opt_GlasgowExts                    `thenTc` \ glaExts ->
-    (if glaExts then
-       returnTc ()
-     else
-       mapTc_ check_constraint context
-    )                                          `thenTc_`
+    mapTc_ check_constraint context                    `thenTc_`
 
        -- Context is already kind-checked
-    tcRecClassContext is_rec context           `thenTc` \ sc_theta ->
+    tcRecTheta is_rec context          `thenTc` \ sc_theta ->
     let
        sc_sel_ids = [mkDictSelId sc_name clas | sc_name <- sc_sel_names]
     in
@@ -235,8 +240,10 @@ tcSuperClasses is_rec clas context sc_sel_names
     returnTc (sc_theta, sc_sel_ids)
 
   where
-    check_constraint sc@(HsPClass c tys) 
-       = checkTc (all is_tyvar tys) (superClassErr clas sc)
+    check_constraint sc = checkTc (ok sc) (superClassErr clas sc)
+    ok (HsClassP c tys) | gla_exts  = True
+                       | otherwise = all is_tyvar tys 
+    ok (HsIParam _ _)  = False         -- Never legal
 
     is_tyvar (HsTyVar _) = True
     is_tyvar other      = False
@@ -279,11 +286,11 @@ tcClassSig is_rec unf_env clas clas_tyvars maybe_dm_env
     let
        -- Build the selector id and default method id
        sel_id = mkDictSelId op_name clas
-       dm_id  = mkDefaultMethodId dm_name clas global_ty
+       dm_id  = mkDefaultMethodId dm_name global_ty
        DefMeth dm_name = sig_dm
 
        dm_info = case maybe_dm_env of
-                   Nothing      -> iface_dm_info
+                   Nothing     -> iface_dm_info
                    Just dm_env -> mk_src_dm_info dm_env
 
        iface_dm_info = case sig_dm of 
@@ -430,32 +437,30 @@ tcDefMeth clas tyvars binds_in prags op_item@(_, DefMeth dm_id)
     let
         theta = [(mkClassPred clas inst_tys)]
     in
-    newDicts origin theta              `thenNF_Tc` \ (this_dict, [this_dict_id]) ->
+    newDicts origin theta              `thenNF_Tc` \ [this_dict] ->
 
     tcExtendTyVarEnvForMeths tyvars clas_tyvars (
         tcMethodBind clas origin clas_tyvars inst_tys theta
                     binds_in prags False op_item
-    )                                  `thenTc` \ (defm_bind, insts_needed, (_, local_dm_id)) ->
+    )                                  `thenTc` \ (defm_bind, insts_needed, local_dm_inst) ->
     
     tcAddErrCtxt (defltMethCtxt clas) $
     
-        -- tcMethodBind has checked that the class_tyvars havn't
-        -- been unified with each other or another type, but we must
-        -- still zonk them before passing them to tcSimplifyAndCheck
-    zonkTcSigTyVars clas_tyvars                `thenNF_Tc` \ clas_tyvars' ->
-    
         -- Check the context
-    tcSimplifyAndCheck
+    tcSimplifyCheck
         (ptext SLIT("class") <+> ppr clas)
-        (mkVarSet clas_tyvars')
-        this_dict
-        insts_needed                   `thenTc` \ (const_lie, dict_binds) ->
+       clas_tyvars
+        [this_dict]
+        insts_needed                           `thenTc` \ (const_lie, dict_binds) ->
+
+       -- Simplification can do unification
+    checkSigTyVars clas_tyvars emptyVarSet     `thenTc` \ clas_tyvars' ->
     
     let
         full_bind = AbsBinds
                    clas_tyvars'
-                   [this_dict_id]
-                   [(clas_tyvars', dm_id, local_dm_id)]
+                   [instToId this_dict]
+                   [(clas_tyvars', dm_id, instToId local_dm_inst)]
                    emptyNameSet        -- No inlines (yet)
                    (dict_binds `andMonoBinds` defm_bind)
     in
@@ -493,18 +498,20 @@ tcMethodBind
        -> [RenamedSig]         -- Pramgas (just for this one)
        -> Bool                 -- True <=> This method is from an instance declaration
        -> ClassOpItem          -- The method selector and default-method Id
-       -> TcM (TcMonoBinds, LIE, (LIE, TcId))
+       -> TcM (TcMonoBinds, LIE, Inst)
 
 tcMethodBind clas origin inst_tyvars inst_tys inst_theta
             meth_binds prags is_inst_decl (sel_id, dm_info)
   = tcGetSrcLoc                        `thenNF_Tc` \ loc -> 
-    newMethod origin sel_id inst_tys   `thenNF_Tc` \ meth@(_, meth_id) ->
-    mkTcSig meth_id loc                        `thenNF_Tc` \ sig_info -> 
+    newMethod origin sel_id inst_tys   `thenNF_Tc` \ meth ->
     let
+       meth_id    = instToId meth
        meth_name  = idName meth_id
        sig_msg    = ptext SLIT("When checking the expected type for class method") <+> ppr sel_id
        meth_prags = find_prags (idName sel_id) meth_name prags
     in
+    mkTcSig meth_id loc                        `thenNF_Tc` \ sig_info -> 
+
        -- Figure out what method binding to use
        -- If the user suppplied one, use it, else construct a default one
     (case find_bind (idName sel_id) meth_name meth_binds of