[project @ 2001-10-25 02:13:10 by sof]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcType.lhs
index d9c6387..7f4e0df 100644 (file)
@@ -36,9 +36,9 @@ module TcType (
   -- Predicates. 
   -- Again, newtypes are opaque
   tcEqType, tcEqPred, tcCmpType, tcCmpTypes, tcCmpPred,
-  isQualifiedTy, isOverloadedTy, isStrictType, isStrictPred,
+  isQualifiedTy, isOverloadedTy, 
   isDoubleTy, isFloatTy, isIntTy,
-  isIntegerTy, isAddrTy, isBoolTy, isUnitTy, isForeignPtrTy, isPrimitiveType,
+  isIntegerTy, isAddrTy, isBoolTy, isUnitTy, isForeignPtrTy, 
   isTauTy, tcIsTyVarTy, tcIsForAllTy,
 
   ---------------------------------
@@ -49,13 +49,23 @@ module TcType (
 
   ---------------------------------
   -- Predicate types  
-  PredType, mkPredTy, mkPredTys, getClassPredTys_maybe, getClassPredTys, 
+  PredType, getClassPredTys_maybe, getClassPredTys, 
   isPredTy, isClassPred, isTyVarClassPred, predHasFDs,
   mkDictTy, tcSplitPredTy_maybe, predTyUnique,
-  isDictTy, tcSplitDFunTy,
+  isDictTy, tcSplitDFunTy, predTyUnique, 
   mkClassPred, predMentionsIPs, inheritablePred, isIPPred, mkPredName,
 
   ---------------------------------
+  -- Foreign import and export
+  isFFIArgumentTy,     -- :: DynFlags -> Safety -> Type -> Bool
+  isFFIImportResultTy, -- :: DynFlags -> Type -> Bool
+  isFFIExportResultTy, -- :: Type -> Bool
+  isFFIExternalTy,     -- :: Type -> Bool
+  isFFIDynArgumentTy,  -- :: Type -> Bool
+  isFFIDynResultTy,    -- :: Type -> Bool
+  isFFILabelTy,        -- :: Type -> Bool
+
+  ---------------------------------
   -- Unifier and matcher  
   unifyTysX, unifyTyListsX, unifyExtendTysX,
   allDistinctTyVars,
@@ -63,20 +73,25 @@ module TcType (
 
   --------------------------------
   -- Rexported from Type
-  Kind, Type, SourceType(..), PredType, ThetaType, 
-  unliftedTypeKind, liftedTypeKind, openTypeKind, mkArrowKind, mkArrowKinds,
+  Kind,        -- Stuff to do with kinds is insensitive to pre/post Tc
+  unliftedTypeKind, liftedTypeKind, openTypeKind, mkArrowKind, mkArrowKinds, 
+  superBoxity, liftedBoxity, hasMoreBoxityInfo, defaultKind, superKind,
+  isTypeKind,
+
+  Type, SourceType(..), PredType, ThetaType, 
   mkForAllTy, mkForAllTys, 
   mkFunTy, mkFunTys, zipFunTys, 
   mkTyConApp, mkAppTy, mkAppTys, mkSynTy, applyTy, applyTys,
-  mkTyVarTy, mkTyVarTys, mkTyConTy,
-  predTyUnique, mkClassPred, 
+  mkTyVarTy, mkTyVarTys, mkTyConTy, mkPredTy, mkPredTys, 
+
   isUnLiftedType,      -- Source types are always lifted
   isUnboxedTupleType,  -- Ditto
+  isPrimitiveType,
+
   tidyTopType, tidyType, tidyPred, tidyTypes, tidyFreeTyVars, tidyOpenType, tidyOpenTypes,
-  tidyTyVar, tidyTyVars,
-  eqKind, eqUsage,
+  tidyTyVarBndr, tidyOpenTyVar, tidyOpenTyVars,
+  typeKind, eqKind, eqUsage,
 
-  -- Reexported ???
   tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tyVarsOfTheta
   ) where
 
@@ -86,26 +101,41 @@ module TcType (
 import {-# SOURCE #-} PprType( pprType )
 
 -- friends:
-import TypeRep         ( Type(..), TyNote(..) )  -- friend
-import Type            -- Lots and lots
-import TyCon           ( TyCon, isPrimTyCon, tyConArity, isNewTyCon )
-import Class           ( classTyCon, classHasFDs, Class )
+import TypeRep         ( Type(..), TyNote(..), funTyCon )  -- friend
+import Type            ( mkUTyM, unUTy )       -- Used locally
+
+import Type            (       -- Re-exports
+                         tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tyVarsOfTheta,
+                         Kind, Type, TauType, SourceType(..), PredType, ThetaType, 
+                         unliftedTypeKind, liftedTypeKind, openTypeKind, mkArrowKind, mkArrowKinds,
+                         mkForAllTy, mkForAllTys, defaultKind, isTypeKind,
+                         mkFunTy, mkFunTys, zipFunTys, 
+                         mkTyConApp, mkAppTy, mkAppTys, mkSynTy, applyTy, applyTys,
+                         mkTyVarTy, mkTyVarTys, mkTyConTy, mkPredTy, mkPredTys,
+                         isUnLiftedType, isUnboxedTupleType, isPrimitiveType,
+                         splitNewType_maybe, splitTyConApp_maybe,
+                         tidyTopType, tidyType, tidyPred, tidyTypes, tidyFreeTyVars, tidyOpenType, tidyOpenTypes,
+                         tidyTyVarBndr, tidyOpenTyVar, tidyOpenTyVars, eqKind, eqUsage,
+                         hasMoreBoxityInfo, liftedBoxity, superBoxity, typeKind, superKind
+                       )
+import TyCon           ( TyCon, isUnLiftedTyCon )
+import Class           ( classHasFDs, Class )
 import Var             ( TyVar, tyVarKind )
+import ForeignCall     ( Safety, playSafe )
 import VarEnv
 import VarSet
 
 -- others:
-import CmdLineOpts     ( opt_DictsStrict )
+import CmdLineOpts     ( DynFlags, DynFlag( Opt_GlasgowExts ), dopt )
 import Name            ( Name, NamedThing(..), mkLocalName )
 import OccName         ( OccName, mkDictOcc )
 import NameSet
-import PrelNames       ( floatTyConKey, doubleTyConKey, foreignPtrTyConKey,
-                         integerTyConKey, intTyConKey, addrTyConKey, boolTyConKey )
-import Unique          ( Unique, Uniquable(..), mkTupleTyConUnique )
+import PrelNames       -- Lots (e.g. in isFFIArgumentTy)
+import TysWiredIn      ( ptrTyCon, funPtrTyCon, addrTyCon, unitTyCon )
+import Unique          ( Unique, Uniquable(..) )
 import SrcLoc          ( SrcLoc )
-import Util            ( cmpList, thenCmp )
+import Util            ( cmpList, thenCmp, equalLength )
 import Maybes          ( maybeToBool, expectJust )
-import BasicTypes      ( Boxity(..) )
 import Outputable
 \end{code}
 
@@ -137,7 +167,7 @@ isTauTy (TyVarTy v)  = True
 isTauTy (TyConApp _ tys) = all isTauTy tys
 isTauTy (AppTy a b)     = isTauTy a && isTauTy b
 isTauTy (FunTy a b)     = isTauTy a && isTauTy b
-isTauTy (SourceTy p)    = isTauTy (sourceTypeRep p)
+isTauTy (SourceTy p)    = True         -- Don't look through source types
 isTauTy (NoteTy _ ty)   = isTauTy ty
 isTauTy (UsageTy _ ty)   = isTauTy ty
 isTauTy other           = False
@@ -327,13 +357,7 @@ tcSplitPredTy_maybe (NoteTy _ ty)              = tcSplitPredTy_maybe ty
 tcSplitPredTy_maybe (UsageTy _ ty)         = tcSplitPredTy_maybe ty
 tcSplitPredTy_maybe (SourceTy p) | isPred p = Just p
 tcSplitPredTy_maybe other                  = Nothing
-
-mkPredTy :: PredType -> Type
-mkPredTy pred = SourceTy pred
-
-mkPredTys :: ThetaType -> [Type]
-mkPredTys preds = map SourceTy preds
-
+       
 predTyUnique :: PredType -> Unique
 predTyUnique (IParam n _)      = getUnique n
 predTyUnique (ClassP clas tys) = getUnique clas
@@ -360,7 +384,7 @@ isClassPred :: SourceType -> Bool
 isClassPred (ClassP clas tys) = True
 isClassPred other            = False
 
-isTyVarClassPred (ClassP clas tys) = all isTyVarTy tys
+isTyVarClassPred (ClassP clas tys) = all tcIsTyVarTy tys
 isTyVarClassPred other            = False
 
 getClassPredTys_maybe :: SourceType -> Maybe (Class, [Type])
@@ -534,7 +558,7 @@ isIntegerTy    = is_tc integerTyConKey
 isIntTy        = is_tc intTyConKey
 isAddrTy       = is_tc addrTyConKey
 isBoolTy       = is_tc boolTyConKey
-isUnitTy       = is_tc (mkTupleTyConUnique Boxed 0)
+isUnitTy       = is_tc unitTyConKey
 
 is_tc :: Unique -> Type -> Bool
 -- Newtypes are opaque to this
@@ -543,36 +567,6 @@ is_tc uniq ty = case tcSplitTyConApp_maybe ty of
                        Nothing      -> False
 \end{code}
 
-\begin{code}
-isPrimitiveType :: Type -> Bool
--- Returns types that are opaque to Haskell.
--- Most of these are unlifted, but now that we interact with .NET, we
--- may have primtive (foreign-imported) types that are lifted
-isPrimitiveType ty = case splitTyConApp_maybe ty of
-                       Just (tc, ty_args) -> ASSERT( length ty_args == tyConArity tc )
-                                             isPrimTyCon tc
-                       other              -> False
-\end{code}
-
-@isStrictType@ computes whether an argument (or let RHS) should
-be computed strictly or lazily, based only on its type
-
-\begin{code}
-isStrictType :: Type -> Bool
-isStrictType ty
-  | isUnLiftedType ty                  = True
-  | Just pred <- tcSplitPredTy_maybe ty = isStrictPred pred
-  | otherwise                          = False
-
-isStrictPred (ClassP clas _) =  opt_DictsStrict
-                            && not (isNewTyCon (classTyCon clas))
-isStrictPred pred           =  False
-       -- We may be strict in dictionary types, but only if it 
-       -- has more than one component.
-       -- [Being strict in a single-component dictionary risks
-       --  poking the dictionary component, which is wrong.]
-\end{code}
-
 
 %************************************************************************
 %*                                                                     *
@@ -650,6 +644,120 @@ namesOfDFunHead dfun_ty = case tcSplitSigmaTy dfun_ty of
 
 %************************************************************************
 %*                                                                     *
+\subsection[TysWiredIn-ext-type]{External types}
+%*                                                                     *
+%************************************************************************
+
+The compiler's foreign function interface supports the passing of a
+restricted set of types as arguments and results (the restricting factor
+being the )
+
+\begin{code}
+isFFIArgumentTy :: DynFlags -> Safety -> Type -> Bool
+-- Checks for valid argument type for a 'foreign import'
+isFFIArgumentTy dflags safety ty 
+   = checkRepTyCon (legalOutgoingTyCon dflags safety) ty
+
+isFFIExternalTy :: Type -> Bool
+-- Types that are allowed as arguments of a 'foreign export'
+isFFIExternalTy ty = checkRepTyCon legalFEArgTyCon ty
+
+isFFIImportResultTy :: DynFlags -> Type -> Bool
+isFFIImportResultTy dflags ty 
+  = checkRepTyCon (legalFIResultTyCon dflags) ty
+
+isFFIExportResultTy :: Type -> Bool
+isFFIExportResultTy ty = checkRepTyCon legalFEResultTyCon ty
+
+isFFIDynArgumentTy :: Type -> Bool
+-- The argument type of a foreign import dynamic must be Ptr, FunPtr, Addr,
+-- or a newtype of either.
+isFFIDynArgumentTy = checkRepTyCon (\tc -> tc == ptrTyCon || tc == funPtrTyCon || tc == addrTyCon)
+
+isFFIDynResultTy :: Type -> Bool
+-- The result type of a foreign export dynamic must be Ptr, FunPtr, Addr,
+-- or a newtype of either.
+isFFIDynResultTy = checkRepTyCon (\tc -> tc == ptrTyCon || tc == funPtrTyCon || tc == addrTyCon)
+
+isFFILabelTy :: Type -> Bool
+-- The type of a foreign label must be Ptr, FunPtr, Addr,
+-- or a newtype of either.
+isFFILabelTy = checkRepTyCon (\tc -> tc == ptrTyCon || tc == funPtrTyCon || tc == addrTyCon)
+
+checkRepTyCon :: (TyCon -> Bool) -> Type -> Bool
+       -- Look through newtypes
+       -- Non-recursive ones are transparent to splitTyConApp,
+       -- but recursive ones aren't; hence the splitNewType_maybe
+checkRepTyCon check_tc ty 
+  | Just ty'    <- splitNewType_maybe ty  = checkRepTyCon check_tc ty'
+  | Just (tc,_) <- splitTyConApp_maybe ty = check_tc tc
+  | otherwise                            = False
+\end{code}
+
+----------------------------------------------
+These chaps do the work; they are not exported
+----------------------------------------------
+
+\begin{code}
+legalFEArgTyCon :: TyCon -> Bool
+-- It's illegal to return foreign objects and (mutable)
+-- bytearrays from a _ccall_ / foreign declaration
+-- (or be passed them as arguments in foreign exported functions).
+legalFEArgTyCon tc
+  | getUnique tc `elem` [ foreignObjTyConKey, foreignPtrTyConKey,
+                         byteArrayTyConKey, mutableByteArrayTyConKey ] 
+  = False
+  -- It's also illegal to make foreign exports that take unboxed
+  -- arguments.  The RTS API currently can't invoke such things.  --SDM 7/2000
+  | otherwise
+  = boxedMarshalableTyCon tc
+
+legalFIResultTyCon :: DynFlags -> TyCon -> Bool
+legalFIResultTyCon dflags tc
+  | getUnique tc `elem`
+       [ foreignObjTyConKey, foreignPtrTyConKey,
+         byteArrayTyConKey, mutableByteArrayTyConKey ]  = False
+  | tc == unitTyCon = True
+  | otherwise      = marshalableTyCon dflags tc
+
+legalFEResultTyCon :: TyCon -> Bool
+legalFEResultTyCon tc
+  | getUnique tc `elem` 
+       [ foreignObjTyConKey, foreignPtrTyConKey,
+         byteArrayTyConKey, mutableByteArrayTyConKey ]  = False
+  | tc == unitTyCon = True
+  | otherwise       = boxedMarshalableTyCon tc
+
+legalOutgoingTyCon :: DynFlags -> Safety -> TyCon -> Bool
+-- Checks validity of types going from Haskell -> external world
+legalOutgoingTyCon dflags safety tc
+  | playSafe safety && getUnique tc `elem` [byteArrayTyConKey, mutableByteArrayTyConKey]
+  = False
+  | otherwise
+  = marshalableTyCon dflags tc
+
+marshalableTyCon dflags tc
+  =  (dopt Opt_GlasgowExts dflags && isUnLiftedTyCon tc)
+  || boxedMarshalableTyCon tc
+
+boxedMarshalableTyCon tc
+   = getUnique tc `elem` [ intTyConKey, int8TyConKey, int16TyConKey
+                        , int32TyConKey, int64TyConKey
+                        , wordTyConKey, word8TyConKey, word16TyConKey
+                        , word32TyConKey, word64TyConKey
+                        , floatTyConKey, doubleTyConKey
+                        , addrTyConKey, ptrTyConKey, funPtrTyConKey
+                        , charTyConKey, foreignObjTyConKey
+                        , foreignPtrTyConKey
+                        , stablePtrTyConKey
+                        , byteArrayTyConKey, mutableByteArrayTyConKey
+                        , boolTyConKey
+                        ]
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
 \subsection{Unification with an explicit substitution}
 %*                                                                     *
 %************************************************************************
@@ -735,13 +843,21 @@ uTysX ty1 (TyVarTy tyvar2) k subst@(tmpls,_)
   | tyvar2 `elemVarSet` tmpls
   = uVarX tyvar2 ty1 k subst
 
+       -- Predicates
+uTysX (SourceTy (IParam n1 t1)) (SourceTy (IParam n2 t2)) k subst
+  | n1 == n2 = uTysX t1 t2 k subst
+uTysX (SourceTy (ClassP c1 tys1)) (SourceTy (ClassP c2 tys2)) k subst
+  | c1 == c2 = uTyListsX tys1 tys2 k subst
+uTysX (SourceTy (NType tc1 tys1)) (SourceTy (NType tc2 tys2)) k subst
+  | tc1 == tc2 = uTyListsX tys1 tys2 k subst
+
        -- Functions; just check the two parts
 uTysX (FunTy fun1 arg1) (FunTy fun2 arg2) k subst
   = uTysX fun1 fun2 (uTysX arg1 arg2 k) subst
 
        -- Type constructors must match
 uTysX (TyConApp con1 tys1) (TyConApp con2 tys2) k subst
-  | (con1 == con2 && length tys1 == length tys2)
+  | (con1 == con2 && equalLength tys1 tys2)
   = uTyListsX tys1 tys2 k subst
 
        -- Applications need a bit of care!
@@ -874,6 +990,15 @@ match (TyVarTy v) ty tmpls k senv
     -- variable may not match the pattern (TyVarTy v') as one would
     -- expect, due to an intervening Note.  KSW 2000-06.
 
+       -- Predicates
+match (SourceTy (IParam n1 t1)) (SourceTy (IParam n2 t2)) tmpls k senv
+  | n1 == n2 = match t1 t2 tmpls k senv
+match (SourceTy (ClassP c1 tys1)) (SourceTy (ClassP c2 tys2)) tmpls k senv
+  | c1 == c2 = match_list_exactly tys1 tys2 tmpls k senv
+match (SourceTy (NType tc1 tys1)) (SourceTy (NType tc2 tys2)) tmpls k senv
+  | tc1 == tc2 = match_list_exactly tys1 tys2 tmpls k senv
+
+       -- Functions; just check the two parts
 match (FunTy arg1 res1) (FunTy arg2 res2) tmpls k senv
   = match arg1 arg2 tmpls (match res1 res2 tmpls k) senv
 
@@ -883,11 +1008,11 @@ match (AppTy fun1 arg1) ty2 tmpls k senv
        Nothing          -> Nothing     -- Fail
 
 match (TyConApp tc1 tys1) (TyConApp tc2 tys2) tmpls k senv
-  | tc1 == tc2 = match_tc_app tys1 tys2 tmpls k senv
+  | tc1 == tc2 = match_list_exactly tys1 tys2 tmpls k senv
 
 -- Newtypes are opaque; other source types should not happen
 match (SourceTy (NType tc1 tys1)) (SourceTy (NType tc2 tys2)) tmpls k senv
-  | tc1 == tc2 = match_tc_app tys1 tys2 tmpls k senv
+  | tc1 == tc2 = match_list_exactly tys1 tys2 tmpls k senv
 
 match (UsageTy _ ty1) ty2 tmpls k senv = match ty1 ty2 tmpls k senv
 match ty1 (UsageTy _ ty2) tmpls k senv = match ty1 ty2 tmpls k senv
@@ -902,7 +1027,7 @@ match ty1      (NoteTy n2 ty2) tmpls k senv = match ty1 ty2 tmpls k senv
 -- Catch-all fails
 match _ _ _ _ _ = Nothing
 
-match_tc_app tys1 tys2 tmpls k senv
+match_list_exactly tys1 tys2 tmpls k senv
   = match_list tys1 tys2 tmpls k' senv
   where
     k' (senv', tys2') | null tys2' = k senv'   -- Succeed