[project @ 1998-01-29 11:38:20 by simonm]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcMonoType.lhs
index 9c68a7d..dad3e7b 100644 (file)
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
 %
 \section[TcMonoType]{Typechecking user-specified @MonoTypes@}
 
 \begin{code}
+module TcMonoType ( tcHsType, tcHsTypeKind, tcContext, tcTyVarScope ) where
+
 #include "HsVersions.h"
 
-module TcMonoType ( tcMonoType, tcInstanceType ) where
+import HsSyn           ( HsType(..), HsTyVar(..), pprContext )
+import RnHsSyn         ( RenamedHsType(..), RenamedContext(..) )
 
-IMPORT_Trace           -- ToDo: rm (debugging)
-import Outputable
-import Pretty
-
-import TcMonad         -- typechecking monad machinery
-import AbsSyn          -- the stuff being typechecked
-
-#ifndef DPH
-import AbsPrel         ( mkListTy, mkTupleTy, mkFunTy )
-#else
-import AbsPrel         ( mkListTy, mkTupleTy, mkFunTy, mkProcessorTy, mkPodTy )
-#endif {- Data Parallel Haskell -}
-import AbsUniType      ( applySynTyCon, applyNonSynTyCon, mkDictTy,
-                         getTyConArity, isSynTyCon, isTyVarTemplateTy,
-                         getUniDataTyCon_maybe, maybeUnpackFunTy
-                         IF_ATTACK_PRAGMAS(COMMA pprTyCon COMMA pprUniType)
-                         IF_ATTACK_PRAGMAS(COMMA cmpUniType)
+import TcMonad
+import TcEnv           ( tcLookupTyVar, tcLookupClass, tcLookupTyCon, tcExtendTyVarEnv )
+import TcKind          ( TcKind, mkBoxedTypeKind, mkTypeKind, mkArrowKind,
+                         unifyKind, unifyKinds, newKindVar,
+                         kindToTcKind, tcDefaultKind
                        )
-import UniType         ( UniType(..) ) -- ******** CHEATING **** could be undone
-import TyCon           --( TyCon(..) ) -- ditto, only more so
-
-import CE              ( lookupCE, CE(..) )
-import CmdLineOpts     ( GlobalSwitch(..) )
-import Errors          ( confusedNameErr, tyConArityErr, instTypeErr,
-                         Error(..)
+import Type            ( Type, ThetaType, 
+                         mkTyVarTy, mkFunTy, mkAppTy, mkSynTy,
+                         mkSigmaTy, mkDictTy, mkTyConApp, mkAppTys
                        )
-import Maybes          ( Maybe(..) )
-import TcPolyType      ( tcPolyType )
-import TCE             ( lookupTCE, TCE(..), UniqFM )
-import TVE             ( lookupTVE, TVE(..) )
-import Util
+import TyVar           ( TyVar, mkTyVar )
+import PrelInfo                ( cCallishClassKeys )
+import TyCon           ( TyCon )
+import Name            ( Name, OccName, isTvOcc, getOccName )
+import TysWiredIn      ( mkListTy, mkTupleTy )
+import Unique          ( Unique, Uniquable(..) )
+import Util            ( zipWithEqual, zipLazy )
+import Outputable
 \end{code}
 
-\begin{code}
-tcMonoType :: CE -> TCE -> TVE -> RenamedMonoType -> Baby_TcM UniType
-
-tcMonoType rec_ce rec_tce tve (MonoTyVar name)
-  = returnB_Tc (lookupTVE tve name)
 
-tcMonoType rec_ce rec_tce tve (ListMonoTy ty)
-  = tcMonoType rec_ce rec_tce tve ty   `thenB_Tc` \ tau_ty ->
-    returnB_Tc (mkListTy tau_ty)
+tcHsType and tcHsTypeKind
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-tcMonoType rec_ce rec_tce tve (TupleMonoTy tys)
-  = mapB_Tc (tcPolyType rec_ce rec_tce tve) tys        `thenB_Tc` \ tau_tys ->
-    returnB_Tc (mkTupleTy (length tau_tys) tau_tys)
+tcHsType checks that the type really is of kind Type!
 
-tcMonoType rec_ce rec_tce tve (FunMonoTy ty1 ty2)
-  = tcMonoType rec_ce rec_tce tve ty1  `thenB_Tc` \ tau_ty1 ->
-    tcMonoType rec_ce rec_tce tve ty2  `thenB_Tc` \ tau_ty2 ->
-    returnB_Tc (mkFunTy tau_ty1 tau_ty2)
-
-tcMonoType rec_ce rec_tce tve (MonoTyCon name@(WiredInTyCon tycon) tys)
-  = let 
-       arity        = getTyConArity tycon
-       is_syn_tycon = isSynTyCon tycon
-    in
-    tcMonoType_help rec_ce rec_tce tve name tycon arity is_syn_tycon tys
-
-tcMonoType rec_ce rec_tce tve (MonoTyCon name@(PreludeTyCon _ _ arity is_data_tycon) tys)
-  = tcMonoType_help rec_ce rec_tce tve name
-                   (lookupTCE rec_tce name)
-                   arity (not is_data_tycon) tys
+\begin{code}
+tcHsType :: RenamedHsType -> TcM s Type
 
+tcHsType ty
+  = tcAddErrCtxt (typeCtxt ty)         $
+    tc_hs_type ty
 
-tcMonoType rec_ce rec_tce tve (MonoTyCon name@(OtherTyCon _ _ arity is_data_tycon _) tys)
-  = tcMonoType_help rec_ce rec_tce tve name
-                   (lookupTCE rec_tce name)
-                   arity (not is_data_tycon) tys
+tc_hs_type ty
+  = tc_hs_type_kind ty                 `thenTc` \ (kind,ty) ->
+       -- Check that it really is a type
+    unifyKind mkTypeKind kind          `thenTc_`
+    returnTc ty
+\end{code}
 
-tcMonoType rec_ce rec_tce tve (MonoTyCon bad_name tys)
-  = getSrcLocB_Tc              `thenB_Tc` \ locn ->
-    failB_Tc (confusedNameErr
-               "Bad name for a type constructor (a class, or a Prelude name?)"
-               bad_name locn)
+tcHsTypeKind does the real work.  It returns a kind and a type.
 
--- two for unfoldings only:
-tcMonoType rec_ce rec_tce tve (MonoDict c ty)
-  = tcMonoType rec_ce rec_tce tve ty   `thenB_Tc` \ new_ty ->
+\begin{code}
+tcHsTypeKind :: RenamedHsType -> TcM s (TcKind s, Type)
+
+tcHsTypeKind ty
+  = tcAddErrCtxt (typeCtxt ty)         $
+    tc_hs_type_kind ty
+
+
+       -- This equation isn't needed (the next one would handle it fine)
+       -- but it's rather a common case, so we handle it directly
+tc_hs_type_kind (MonoTyVar name)
+  | isTvOcc (getOccName name)
+  = tcLookupTyVar name                 `thenNF_Tc` \ (kind,tyvar) ->
+    returnTc (kind, mkTyVarTy tyvar)
+
+tc_hs_type_kind ty@(MonoTyVar name)
+  = tcFunType ty []
+    
+tc_hs_type_kind (MonoListTy _ ty)
+  = tc_hs_type ty      `thenTc` \ tau_ty ->
+    returnTc (mkBoxedTypeKind, mkListTy tau_ty)
+
+tc_hs_type_kind (MonoTupleTy _ tys)
+  = mapTc tc_hs_type  tys      `thenTc` \ tau_tys ->
+    returnTc (mkBoxedTypeKind, mkTupleTy (length tys) tau_tys)
+
+tc_hs_type_kind (MonoFunTy ty1 ty2)
+  = tc_hs_type ty1     `thenTc` \ tau_ty1 ->
+    tc_hs_type ty2     `thenTc` \ tau_ty2 ->
+    returnTc (mkBoxedTypeKind, mkFunTy tau_ty1 tau_ty2)
+
+tc_hs_type_kind (MonoTyApp ty1 ty2)
+  = tcTyApp ty1 [ty2]
+
+tc_hs_type_kind (HsForAllTy tv_names context ty)
+  = tcTyVarScope tv_names                      $ \ tyvars ->
+       tcContext context                       `thenTc` \ theta ->
+       tc_hs_type ty                           `thenTc` \ tau ->
+               -- For-all's are of kind type!
+       returnTc (mkBoxedTypeKind, mkSigmaTy tyvars theta tau)
+
+-- for unfoldings, and instance decls, only:
+tc_hs_type_kind (MonoDictTy class_name tys)
+  = mapAndUnzipTc tc_hs_type_kind tys  `thenTc` \ (arg_kinds, arg_tys) ->
+    tcLookupClass class_name           `thenTc` \ (class_kinds, clas) ->
     let
-       clas = lookupCE rec_ce c
+       arity  = length class_kinds
+       n_args = length arg_kinds
+       err = arityErr "Class" class_name arity n_args
     in
-    returnB_Tc (mkDictTy clas new_ty)
-
-tcMonoType rec_ce rec_tce tve (MonoTyVarTemplate tv_tmpl)
-  = returnB_Tc (lookupTVE tve tv_tmpl)
-
-#ifdef DPH
-tcMonoType ce tce tve (MonoTyProc tys ty)
-  = tcMonoTypes ce tce tve tys `thenB_Tc` \ tau_tys ->
-    tcMonoType ce tce tve ty   `thenB_Tc` \ tau_ty  ->
-    returnB_Tc (mkProcessorTy tau_tys tau_ty)
-
-tcMonoType ce tce tve (MonoTyPod ty)
-  = tcMonoType ce tce tve ty   `thenB_Tc` \ tau_ty  ->
-    returnB_Tc (mkPodTy tau_ty)
-#endif {- Data Parallel Haskell -}
-
-#ifdef DEBUG
-tcMonoType rec_ce rec_tce tve bad_ty
-  = pprPanic "tcMonoType:" (ppr PprShowAll bad_ty)
-#endif
+    checkTc (arity == n_args) err      `thenTc_`
+    unifyKinds class_kinds arg_kinds   `thenTc_`
+    returnTc (mkBoxedTypeKind, mkDictTy clas arg_tys)
 \end{code}
 
+Help functions for type applications
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 \begin{code}
-tcMonoType_help rec_ce rec_tce tve name tycon arity is_syn_tycon tys
-  = tcMonoTypes rec_ce rec_tce tve tys `thenB_Tc`    \ tau_tys ->
-    let         cur_arity = length tys  in
-    getSrcLocB_Tc                      `thenB_Tc` \ loc ->
-
-    checkB_Tc (arity /= cur_arity)
-          (tyConArityErr name arity cur_arity loc) `thenB_Tc_`
-
-    returnB_Tc (if is_syn_tycon then
-                applySynTyCon  tycon tau_tys
-             else
-                applyNonSynTyCon tycon tau_tys)
-
--- also not exported
-tcMonoTypes rec_ce rec_tce tve monotypes
-   = mapB_Tc (tcMonoType rec_ce rec_tce tve) monotypes
+tcTyApp (MonoTyApp ty1 ty2) tys
+  = tcTyApp ty1 (ty2:tys)
+
+tcTyApp ty tys
+  | null tys
+  = tcFunType ty []
+
+  | otherwise
+  = mapAndUnzipTc tc_hs_type_kind tys  `thenTc` \ (arg_kinds, arg_tys) ->
+    tcFunType ty arg_tys               `thenTc` \ (fun_kind, result_ty) ->
+
+       -- Check argument compatibility
+    newKindVar                         `thenNF_Tc` \ result_kind ->
+    unifyKind fun_kind (foldr mkArrowKind result_kind arg_kinds)
+                                       `thenTc_`
+    returnTc (result_kind, result_ty)
+
+-- (tcFunType ty arg_tys) returns (kind-of ty, mkAppTys ty arg_tys)
+-- But not quite; for synonyms it checks the correct arity, and builds a SynTy
+--     hence the rather strange functionality.
+
+tcFunType (MonoTyVar name) arg_tys
+  | isTvOcc (getOccName name)  -- Must be a type variable
+  = tcLookupTyVar name                 `thenNF_Tc` \ (kind,tyvar) ->
+    returnTc (kind, mkAppTys (mkTyVarTy tyvar) arg_tys)
+
+  | otherwise                  -- Must be a type constructor
+  = tcLookupTyCon name                 `thenTc` \ (tycon_kind,maybe_arity, tycon) ->
+    case maybe_arity of
+       Nothing    ->   -- Data type or newtype 
+                     returnTc (tycon_kind, mkTyConApp tycon arg_tys)
+
+       Just arity ->   -- Type synonym
+                     checkTc (arity <= n_args) err_msg `thenTc_`
+                     returnTc (tycon_kind, result_ty)
+                  where
+                       -- It's OK to have an *over-applied* type synonym
+                       --      data Tree a b = ...
+                       --      type Foo a = Tree [a]
+                       --      f :: Foo a b -> ...
+                     result_ty = mkAppTys (mkSynTy tycon (take arity arg_tys))
+                                          (drop arity arg_tys)
+                     err_msg = arityErr "Type synonym constructor" name arity n_args
+                     n_args  = length arg_tys
+
+tcFunType ty arg_tys
+  = tc_hs_type_kind ty         `thenTc` \ (fun_kind, fun_ty) ->
+    returnTc (fun_kind, mkAppTys fun_ty arg_tys)
 \end{code}
 
-@tcInstanceType@ checks the type {\em and} its syntactic constraints:
-it must normally look like: @instance Foo (Tycon a b c ...) ...@
-(We're checking the @Tycon a b c ...@ part here...)
 
-The exceptions to this syntactic checking: (1)~if the @GlasgowExts@
-flag is on, or (2)~the instance is imported (they must have been
-compiled elsewhere).  In these cases, we let them go through anyway.
+Contexts
+~~~~~~~~
+\begin{code}
+
+tcContext :: RenamedContext -> TcM s ThetaType
+tcContext context = tcAddErrCtxt (thetaCtxt context) $
+                   mapTc tcClassAssertion context
+
+tcClassAssertion (class_name, tys)
+  = checkTc (canBeUsedInContext class_name)
+           (naughtyCCallContextErr class_name) `thenTc_`
 
-We can also have instances for functions: @instance Foo (a -> b) ...@.
+    tcLookupClass class_name           `thenTc` \ (class_kinds, clas) ->
+    mapAndUnzipTc tc_hs_type_kind tys  `thenTc` \ (ty_kinds, tc_tys) ->
+
+    unifyKinds class_kinds ty_kinds    `thenTc_`
+
+    returnTc (clas, tc_tys)
+\end{code}
+
+HACK warning: Someone discovered that @CCallable@ and @CReturnable@
+could be used in contexts such as:
+\begin{verbatim}
+foo :: CCallable a => a -> PrimIO Int
+\end{verbatim}
+
+Doing this utterly wrecks the whole point of introducing these
+classes so we specifically check that this isn't being done.
 
 \begin{code}
-tcInstanceType :: CE -> TCE -> TVE
-              -> Bool{-True <=> from this module-} -> SrcLoc
-              -> RenamedMonoType
-              -> Baby_TcM UniType
+canBeUsedInContext :: Name -> Bool
+canBeUsedInContext n = not (uniqueOf n `elem` cCallishClassKeys)
+\end{code}
 
-tcInstanceType ce tce tve from_here locn mono_ty
-  = tcMonoType ce tce tve mono_ty      `thenB_Tc` \ tau_ty  ->
-    let
-       (naughty, unkosher) = bad_shape tau_ty
-    in
-    getSwitchCheckerB_Tc               `thenB_Tc` \ sw_chkr ->
-    checkB_Tc
-       (if not from_here || sw_chkr GlasgowExts then -- no "shape" checking
-           naughty
-        else
-           naughty || unkosher
-       )
-       (instTypeErr tau_ty locn)       `thenB_Tc_`
-    returnB_Tc tau_ty
-  where
-    -- "naughty" if the type is really unacceptable, no
-    -- matter what (e.g., a type synonym); "unkosher" if
-    -- the Haskell report forbids it, but we allow it through
-    -- under -fglasgow-exts.
-
-    bad_shape ty
-      = if (is_syn_type ty) then
-          (True, bottom)
-       else case (getUniDataTyCon_maybe ty) of
-         Just (_,tys,_) -> (False, not (all isTyVarTemplateTy tys))
-         Nothing        -> case maybeUnpackFunTy ty of
-                             Just (t1, t2) -> (False,
-                                               not (all isTyVarTemplateTy [t1, t2]))
-                             Nothing       -> (True, bottom)
-      where
-       bottom = panic "bad_shape"
-
-       is_syn_type ty -- ToDo: move to AbsUniType (or friend)?
-         = case ty of
-             UniSyn _ _ _ -> True
-             _ -> False
+Type variables, with knot tying!
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\begin{code}
+tcTyVarScope
+       :: [HsTyVar Name]               -- Names of some type variables
+       -> ([TyVar] -> TcM s a)         -- Thing to type check in their scope
+       -> TcM s a                      -- Result
+
+tcTyVarScope tyvar_names thing_inside
+  = mapAndUnzipNF_Tc tcHsTyVar tyvar_names     `thenNF_Tc` \ (names, kinds) ->
+
+    fixTc (\ ~(rec_tyvars, _) ->
+               -- Ok to look at names, kinds, but not tyvars!
+
+       tcExtendTyVarEnv names (kinds `zipLazy` rec_tyvars)
+                        (thing_inside rec_tyvars)              `thenTc` \ result ->
+               -- Get the tyvar's Kinds from their TcKinds
+       mapNF_Tc tcDefaultKind kinds                            `thenNF_Tc` \ kinds' ->
+
+               -- Construct the real TyVars
+       let
+         tyvars = zipWithEqual "tcTyVarScope" mkTyVar names kinds'
+       in
+       returnTc (tyvars, result)
+    )                                  `thenTc` \ (_,result) ->
+    returnTc result
+
+tcHsTyVar (UserTyVar name)
+  = newKindVar         `thenNF_Tc` \ tc_kind ->
+    returnNF_Tc (name, tc_kind)
+tcHsTyVar (IfaceTyVar name kind)
+  = returnNF_Tc (name, kindToTcKind kind)
+\end{code}
+
+Errors and contexts
+~~~~~~~~~~~~~~~~~~~
+\begin{code}
+naughtyCCallContextErr clas_name
+  = sep [ptext SLIT("Can't use class"), quotes (ppr clas_name), ptext SLIT("in a context")]
+
+typeCtxt ty = ptext SLIT("In the type") <+> quotes (ppr ty)
+
+thetaCtxt theta = ptext SLIT("In the context") <+> quotes (pprContext theta)
 \end{code}