mkSynTy,
- repType, typePrimRep, coreView, deepCoreView,
+ repType, typePrimRep, coreView, tcView,
mkForAllTy, mkForAllTys, splitForAllTy_maybe, splitForAllTys,
applyTy, applyTys, isForAllTy, dropForAlls,
import TyCon ( TyCon, isRecursiveTyCon, isPrimTyCon,
isUnboxedTupleTyCon, isUnLiftedTyCon,
isFunTyCon, isNewTyCon, newTyConRep, newTyConRhs,
- isAlgTyCon, isSynTyCon, tyConArity, newTyConRhs_maybe,
- tyConKind, getSynTyConDefn, PrimRep(..), tyConPrimRep,
+ isAlgTyCon, tyConArity,
+ tcExpandTyCon_maybe, coreExpandTyCon_maybe,
+ tyConKind, PrimRep(..), tyConPrimRep,
)
-- others
import StaticFlags ( opt_DictsStrict )
import SrcLoc ( noSrcLoc )
import Unique ( Uniquable(..) )
-import Util ( mapAccumL, seqList, lengthIs, snocView, thenCmp, isEqual )
+import Util ( mapAccumL, seqList, lengthIs, snocView, thenCmp, isEqual, all2 )
import Outputable
import UniqSet ( sizeUniqSet ) -- Should come via VarSet
import Maybe ( isJust )
-- its underlying representation type.
-- Returns Nothing if there is nothing to look through.
--
--- By being non-recursive and inlined, this case analysis gets efficiently
--- joined onto the case analysis that the caller is already doing
-coreView (NoteTy _ ty) = Just ty
-coreView (PredTy p) = Just (predTypeRep p)
-coreView (TyConApp tc tys) = expandNewTcApp tc tys
-coreView ty = Nothing
-
-deepCoreView :: Type -> Type
--- Apply coreView recursively
-deepCoreView ty
- | Just ty' <- coreView ty = deepCoreView ty'
-deepCoreView (TyVarTy tv) = TyVarTy tv
-deepCoreView (TyConApp tc tys) = TyConApp tc (map deepCoreView tys)
-deepCoreView (AppTy t1 t2) = AppTy (deepCoreView t1) (deepCoreView t2)
-deepCoreView (FunTy t1 t2) = FunTy (deepCoreView t1) (deepCoreView t2)
-deepCoreView (ForAllTy tv ty) = ForAllTy tv (deepCoreView ty)
- -- No NoteTy, no PredTy
-
-expandNewTcApp :: TyCon -> [Type] -> Maybe Type
--- A local helper function (not exported)
--- Expands *the outermoset level of* a newtype application to
+-- In the case of newtypes, it returns
-- *either* a vanilla TyConApp (recursive newtype, or non-saturated)
-- *or* the newtype representation (otherwise), meaning the
-- type written in the RHS of the newtype decl,
-- on S gives Just T
-- on T gives Nothing (no expansion)
-expandNewTcApp tc tys = case newTyConRhs_maybe tc tys of
- Nothing -> Nothing
- Just (tenv, rhs) -> Just (substTy (mkTopTvSubst tenv) rhs)
+-- By being non-recursive and inlined, this case analysis gets efficiently
+-- joined onto the case analysis that the caller is already doing
+coreView (NoteTy _ ty) = Just ty
+coreView (PredTy p) = Just (predTypeRep p)
+coreView (TyConApp tc tys) | Just (tenv, rhs, tys') <- coreExpandTyCon_maybe tc tys
+ = Just (mkAppTys (substTy (mkTopTvSubst tenv) rhs) tys')
+ -- Its important to use mkAppTys, rather than (foldl AppTy),
+ -- because the function part might well return a
+ -- partially-applied type constructor; indeed, usually will!
+coreView ty = Nothing
+
+-----------------------------------------------
+{-# INLINE tcView #-}
+tcView :: Type -> Maybe Type
+-- Same, but for the type checker, which just looks through synonyms
+tcView (NoteTy _ ty) = Just ty
+tcView (TyConApp tc tys) | Just (tenv, rhs, tys') <- tcExpandTyCon_maybe tc tys
+ = Just (mkAppTys (substTy (mkTopTvSubst tenv) rhs) tys')
+tcView ty = Nothing
\end{code}
\begin{code}
mkGenTyConApp :: TyCon -> [Type] -> Type
mkGenTyConApp tc tys
- | isSynTyCon tc = mkSynTy tc tys
- | otherwise = mkTyConApp tc tys
+ = mkTyConApp tc tys
mkTyConApp :: TyCon -> [Type] -> Type
--- Assumes TyCon is not a SynTyCon; use mkSynTy instead for those
mkTyConApp tycon tys
| isFunTyCon tycon, [ty1,ty2] <- tys
= FunTy ty1 ty2
| otherwise
- = ASSERT(not (isSynTyCon tycon))
- TyConApp tycon tys
+ = TyConApp tycon tys
mkTyConTy :: TyCon -> Type
mkTyConTy tycon = mkTyConApp tycon []
~~~~~
\begin{code}
-mkSynTy tycon tys
+mkSynTy tycon tys = panic "No longer used"
+{- Delete in due course
| n_args == arity -- Exactly saturated
= mk_syn tys
| n_args > arity -- Over-saturated
(tyvars, body) = ASSERT( isSynTyCon tycon ) getSynTyConDefn tycon
arity = tyConArity tycon
n_args = length tys
+-}
\end{code}
Notes on type synonyms
tyVarsOfType (TyVarTy tv) = unitVarSet tv
tyVarsOfType (TyConApp tycon tys) = tyVarsOfTypes tys
tyVarsOfType (NoteTy (FTVNote tvs) ty2) = tvs
-tyVarsOfType (NoteTy (SynNote ty1) ty2) = tyVarsOfType ty2 -- See note [Syn] below
tyVarsOfType (PredTy sty) = tyVarsOfPred sty
tyVarsOfType (FunTy arg res) = tyVarsOfType arg `unionVarSet` tyVarsOfType res
tyVarsOfType (AppTy fun arg) = tyVarsOfType fun `unionVarSet` tyVarsOfType arg
where
(envp, tvp) = tidyTyVarBndr env tv
- go_note (SynNote ty) = SynNote $! (go ty)
go_note note@(FTVNote ftvs) = note -- No need to tidy the free tyvars
tidyTypes env tys = map (tidyType env) tys
seqTypes (ty:tys) = seqType ty `seq` seqTypes tys
seqNote :: TyNote -> ()
-seqNote (SynNote ty) = seqType ty
seqNote (FTVNote set) = sizeUniqSet set `seq` ()
seqPred :: PredType -> ()
%************************************************************************
%* *
- Comparison of types
+ Equality for Core types
(We don't use instances so that we know where it happens)
%* *
%************************************************************************
-Two flavours:
+Note that eqType works right even for partial applications of newtypes.
+See Note [Newtype eta] in TyCon.lhs
+
+\begin{code}
+coreEqType :: Type -> Type -> Bool
+coreEqType t1 t2
+ = eq rn_env t1 t2
+ where
+ rn_env = mkRnEnv2 (mkInScopeSet (tyVarsOfType t1 `unionVarSet` tyVarsOfType t2))
+
+ eq env (TyVarTy tv1) (TyVarTy tv2) = rnOccL env tv1 == rnOccR env tv2
+ eq env (ForAllTy tv1 t1) (ForAllTy tv2 t2) = eq (rnBndr2 env tv1 tv2) t1 t2
+ eq env (AppTy s1 t1) (AppTy s2 t2) = eq env s1 s2 && eq env t1 t2
+ eq env (FunTy s1 t1) (FunTy s2 t2) = eq env s1 s2 && eq env t1 t2
+ eq env (TyConApp tc1 tys1) (TyConApp tc2 tys2)
+ | tc1 == tc2, all2 (eq env) tys1 tys2 = True
+ -- The lengths should be equal because
+ -- the two types have the same kind
+ -- NB: if the type constructors differ that does not
+ -- necessarily mean that the types aren't equal
+ -- (synonyms, newtypes)
+ -- Even if the type constructors are the same, but the arguments
+ -- differ, the two types could be the same (e.g. if the arg is just
+ -- ignored in the RHS). In both these cases we fall through to an
+ -- attempt to expand one side or the other.
+
+ -- Now deal with newtypes, synonyms, pred-tys
+ eq env t1 t2 | Just t1' <- coreView t1 = eq env t1' t2
+ | Just t2' <- coreView t2 = eq env t1 t2'
+
+ -- Fall through case; not equal!
+ eq env t1 t2 = False
+\end{code}
-* tcEqType, tcCmpType do *not* look through newtypes, PredTypes
-* coreEqType *does* look through them
-Note that eqType can respond 'False' for partial applications of newtypes.
-Consider
- newtype Parser m a = MkParser (Foogle m a)
-Does
- Monad (Parser m) `eqType` Monad (Foogle m)
-Well, yes, but eqType won't see that they are the same.
-I don't think this is harmful, but it's soemthing to watch out for.
+%************************************************************************
+%* *
+ Comparision for source types
+ (We don't use instances so that we know where it happens)
+%* *
+%************************************************************************
-First, the external interface
+Note that
+ tcEqType, tcCmpType
+do *not* look through newtypes, PredTypes
\begin{code}
-coreEqType :: Type -> Type -> Bool
-coreEqType t1 t2 = isEqual $ cmpType (deepCoreView t1) (deepCoreView t2)
-
tcEqType :: Type -> Type -> Bool
tcEqType t1 t2 = isEqual $ cmpType t1 t2
rn_env = mkRnEnv2 (mkInScopeSet (tyVarsOfPred p1 `unionVarSet` tyVarsOfPred p2))
cmpTypeX :: RnEnv2 -> Type -> Type -> Ordering -- Main workhorse
-
--- NB: we *cannot* short-cut the newtype comparison thus:
--- eqTypeX env (NewTcApp tc1 tys1) (NewTcApp tc2 tys2)
--- | (tc1 == tc2) = (eqTypeXs env tys1 tys2)
---
--- Consider:
--- newtype T a = MkT [a]
--- newtype Foo m = MkFoo (forall a. m a -> Int)
--- w1 :: Foo []
--- w1 = ...
---
--- w2 :: Foo T
--- w2 = MkFoo (\(MkT x) -> case w1 of MkFoo f -> f x)
---
--- We end up with w2 = w1; so we need that Foo T = Foo []
--- but we can only expand saturated newtypes, so just comparing
--- T with [] won't do.
+cmpTypeX env t1 t2 | Just t1' <- tcView t1 = cmpTypeX env t1' t2
+ | Just t2' <- tcView t2 = cmpTypeX env t1 t2'
cmpTypeX env (TyVarTy tv1) (TyVarTy tv2) = rnOccL env tv1 `compare` rnOccR env tv2
cmpTypeX env (ForAllTy tv1 t1) (ForAllTy tv2 t2) = cmpTypeX (rnBndr2 env tv1 tv2) t1 t2
cmpTypeX env (FunTy s1 t1) (FunTy s2 t2) = cmpTypeX env s1 s2 `thenCmp` cmpTypeX env t1 t2
cmpTypeX env (PredTy p1) (PredTy p2) = cmpPredX env p1 p2
cmpTypeX env (TyConApp tc1 tys1) (TyConApp tc2 tys2) = (tc1 `compare` tc2) `thenCmp` cmpTypesX env tys1 tys2
-cmpTypeX env (NoteTy _ t1) t2 = cmpTypeX env t1 t2
cmpTypeX env t1 (NoteTy _ t2) = cmpTypeX env t1 t2
-- Deal with the rest: TyVarTy < AppTy < FunTy < TyConApp < ForAllTy < PredTy
subst1 = TvSubst in_scope env1
emptyTvSubst = TvSubst emptyInScopeSet emptyVarEnv
+
isEmptyTvSubst :: TvSubst -> Bool
isEmptyTvSubst (TvSubst _ env) = isEmptyVarEnv env
substTys subst tys | isEmptyTvSubst subst = tys
| otherwise = map (subst_ty subst) tys
-deShadowTy :: Type -> Type -- Remove any shadowing from the type
-deShadowTy ty = subst_ty emptyTvSubst ty
-
substTheta :: TvSubst -> ThetaType -> ThetaType
substTheta subst theta
| isEmptyTvSubst subst = theta
substPred subst (IParam n ty) = IParam n (subst_ty subst ty)
substPred subst (ClassP clas tys) = ClassP clas (map (subst_ty subst) tys)
+deShadowTy :: TyVarSet -> Type -> Type -- Remove any nested binders mentioning tvs
+deShadowTy tvs ty
+ = subst_ty (mkTvSubst in_scope emptyTvSubstEnv) ty
+ where
+ in_scope = mkInScopeSet tvs
+
-- Note that the in_scope set is poked only if we hit a forall
-- so it may often never be fully computed
subst_ty subst ty
go (PredTy p) = PredTy $! (substPred subst p)
- go (NoteTy (SynNote ty1) ty2) = NoteTy (SynNote $! (go ty1)) $! (go ty2)
go (NoteTy (FTVNote _) ty2) = go ty2 -- Discard the free tyvar note
go (FunTy arg res) = (FunTy $! (go arg)) $! (go res)