summaryrefslogtreecommitdiff
path: root/compiler/typecheck/TcType.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/typecheck/TcType.hs')
-rw-r--r--compiler/typecheck/TcType.hs166
1 files changed, 73 insertions, 93 deletions
diff --git a/compiler/typecheck/TcType.hs b/compiler/typecheck/TcType.hs
index 8b91ed04f7..80883e4e48 100644
--- a/compiler/typecheck/TcType.hs
+++ b/compiler/typecheck/TcType.hs
@@ -1711,8 +1711,8 @@ tcEqType :: HasDebugCallStack => TcType -> TcType -> Bool
-- equality] (in TyCoRep) as `eqType`, but Type.eqType believes (* ==
-- Constraint), and that is NOT what we want in the type checker!
tcEqType ty1 ty2
- = isNothing (tc_eq_type tcView ki1 ki2) &&
- isNothing (tc_eq_type tcView ty1 ty2)
+ = tc_eq_type False False ki1 ki2
+ && tc_eq_type False False ty1 ty2
where
ki1 = tcTypeKind ty1
ki2 = tcTypeKind ty2
@@ -1721,93 +1721,83 @@ tcEqType ty1 ty2
-- as long as their non-coercion structure is identical.
tcEqTypeNoKindCheck :: TcType -> TcType -> Bool
tcEqTypeNoKindCheck ty1 ty2
- = isNothing $ tc_eq_type tcView ty1 ty2
-
--- | Like 'tcEqType', but returns information about whether the difference
--- is visible in the case of a mismatch.
--- @Nothing@ : the types are equal
--- @Just True@ : the types differ, and the point of difference is visible
--- @Just False@ : the types differ, and the point of difference is invisible
-tcEqTypeVis :: TcType -> TcType -> Maybe Bool
-tcEqTypeVis ty1 ty2
- = tc_eq_type tcView ty1 ty2 <!> invis (tc_eq_type tcView ki1 ki2)
- where
- ki1 = tcTypeKind ty1
- ki2 = tcTypeKind ty2
+ = tc_eq_type True True ty1 ty2
- -- convert Just True to Just False
- invis :: Maybe Bool -> Maybe Bool
- invis = fmap (const False)
+-- | Like 'tcEqType', but returns True if the /visible/ part of the types
+-- are equal, even if they are really unequal (in the invisible bits)
+tcEqTypeVis :: TcType -> TcType -> Bool
+tcEqTypeVis ty1 ty2 = tc_eq_type True False ty1 ty2
-(<!>) :: Maybe Bool -> Maybe Bool -> Maybe Bool
-Nothing <!> x = x
-Just True <!> _ = Just True
-Just _vis <!> Just True = Just True
-Just vis <!> _ = Just vis
-infixr 3 <!>
+-- | Like 'pickyEqTypeVis', but returns a Bool for convenience
+pickyEqType :: TcType -> TcType -> Bool
+-- Check when two types _look_ the same, _including_ synonyms.
+-- So (pickyEqType String [Char]) returns False
+-- This ignores kinds and coercions, because this is used only for printing.
+pickyEqType ty1 ty2 = tc_eq_type True True ty1 ty2
-- | Real worker for 'tcEqType'. No kind check!
-tc_eq_type :: (TcType -> Maybe TcType) -- ^ @tcView@, if you want unwrapping
- -> Type -> Type -> Maybe Bool
-tc_eq_type view_fun orig_ty1 orig_ty2 = go True orig_env orig_ty1 orig_ty2
+tc_eq_type :: Bool -- ^ True <=> do not expand type synonyms
+ -> Bool -- ^ True <=> compare visible args only
+ -> Type -> Type
+ -> Bool
+-- Flags False, False is the usual setting for tc_eq_type
+tc_eq_type keep_syns vis_only orig_ty1 orig_ty2
+ = go orig_env orig_ty1 orig_ty2
where
- go :: Bool -> RnEnv2 -> Type -> Type -> Maybe Bool
- go vis env t1 t2 | Just t1' <- view_fun t1 = go vis env t1' t2
- go vis env t1 t2 | Just t2' <- view_fun t2 = go vis env t1 t2'
+ go :: RnEnv2 -> Type -> Type -> Bool
+ go env t1 t2 | not keep_syns, Just t1' <- tcView t1 = go env t1' t2
+ go env t1 t2 | not keep_syns, Just t2' <- tcView t2 = go env t1 t2'
- go vis env (TyVarTy tv1) (TyVarTy tv2)
- = check vis $ rnOccL env tv1 == rnOccR env tv2
+ go env (TyVarTy tv1) (TyVarTy tv2)
+ = rnOccL env tv1 == rnOccR env tv2
- go vis _ (LitTy lit1) (LitTy lit2)
- = check vis $ lit1 == lit2
+ go _ (LitTy lit1) (LitTy lit2)
+ = lit1 == lit2
+
+ go env (ForAllTy (Bndr tv1 vis1) ty1)
+ (ForAllTy (Bndr tv2 vis2) ty2)
+ = vis1 == vis2
+ && (vis_only || go env (varType tv1) (varType tv2))
+ && go (rnBndr2 env tv1 tv2) ty1 ty2
- go vis env (ForAllTy (Bndr tv1 vis1) ty1)
- (ForAllTy (Bndr tv2 vis2) ty2)
- = go (isVisibleArgFlag vis1) env (varType tv1) (varType tv2)
- <!> go vis (rnBndr2 env tv1 tv2) ty1 ty2
- <!> check vis (vis1 == vis2)
-- Make sure we handle all FunTy cases since falling through to the
-- AppTy case means that tcRepSplitAppTy_maybe may see an unzonked
-- kind variable, which causes things to blow up.
- go vis env (FunTy arg1 res1) (FunTy arg2 res2)
- = go vis env arg1 arg2 <!> go vis env res1 res2
- go vis env ty (FunTy arg res)
- = eqFunTy vis env arg res ty
- go vis env (FunTy arg res) ty
- = eqFunTy vis env arg res ty
+ go env (FunTy arg1 res1) (FunTy arg2 res2)
+ = go env arg1 arg2 && go env res1 res2
+ go env ty (FunTy arg res) = eqFunTy env arg res ty
+ go env (FunTy arg res) ty = eqFunTy env arg res ty
-- See Note [Equality on AppTys] in Type
- go vis env (AppTy s1 t1) ty2
+ go env (AppTy s1 t1) ty2
| Just (s2, t2) <- tcRepSplitAppTy_maybe ty2
- = go vis env s1 s2 <!> go vis env t1 t2
- go vis env ty1 (AppTy s2 t2)
+ = go env s1 s2 && go env t1 t2
+ go env ty1 (AppTy s2 t2)
| Just (s1, t1) <- tcRepSplitAppTy_maybe ty1
- = go vis env s1 s2 <!> go vis env t1 t2
- go vis env (TyConApp tc1 ts1) (TyConApp tc2 ts2)
- = check vis (tc1 == tc2) <!> gos (tc_vis vis tc1) env ts1 ts2
- go vis env (CastTy t1 _) t2 = go vis env t1 t2
- go vis env t1 (CastTy t2 _) = go vis env t1 t2
- go _ _ (CoercionTy {}) (CoercionTy {}) = Nothing
- go vis _ _ _ = Just vis
-
- gos _ _ [] [] = Nothing
- gos (v:vs) env (t1:ts1) (t2:ts2) = go v env t1 t2 <!> gos vs env ts1 ts2
- gos (v:_) _ _ _ = Just v
- gos _ _ _ _ = panic "tc_eq_type"
-
- tc_vis :: Bool -> TyCon -> [Bool]
- tc_vis True tc = viss ++ repeat True
- -- the repeat True is necessary because tycons can legitimately
- -- be oversaturated
+ = go env s1 s2 && go env t1 t2
+
+ go env (TyConApp tc1 ts1) (TyConApp tc2 ts2)
+ = tc1 == tc2 && gos env (tc_vis tc1) ts1 ts2
+
+ go env (CastTy t1 _) t2 = go env t1 t2
+ go env t1 (CastTy t2 _) = go env t1 t2
+ go _ (CoercionTy {}) (CoercionTy {}) = True
+
+ go _ _ _ = False
+
+ gos _ _ [] [] = True
+ gos env (ig:igs) (t1:ts1) (t2:ts2) = (ig || go env t1 t2)
+ && gos env igs ts1 ts2
+ gos _ _ _ _ = False
+
+ tc_vis :: TyCon -> [Bool] -- True for the fields we should ignore
+ tc_vis tc | vis_only = inviss ++ repeat False -- Ignore invisibles
+ | otherwise = repeat False -- Ignore nothing
+ -- The repeat False is necessary because tycons
+ -- can legitimately be oversaturated
where
bndrs = tyConBinders tc
- viss = map isVisibleTyConBinder bndrs
- tc_vis False _ = repeat False -- if we're not in a visible context, our args
- -- aren't either
-
- check :: Bool -> Bool -> Maybe Bool
- check _ True = Nothing
- check vis False = Just vis
+ inviss = map isInvisibleTyConBinder bndrs
orig_env = mkRnEnv2 $ mkInScopeSet $ tyCoVarsOfTypes [orig_ty1, orig_ty2]
@@ -1817,30 +1807,20 @@ tc_eq_type view_fun orig_ty1 orig_ty2 = go True orig_env orig_ty1 orig_ty2
-- always extract a RuntimeRep (see Note [xyz]) if the kind of the arg or
-- res is unzonked/unflattened. Thus this function, which handles this
-- corner case.
- eqFunTy :: Bool -> RnEnv2 -> Type -> Type -> Type -> Maybe Bool
- eqFunTy vis env arg res (FunTy arg' res')
- = go vis env arg arg' <!> go vis env res res'
- eqFunTy vis env arg res ty@(AppTy{})
- | Just (tc, [_, _, arg', res']) <- get_args ty []
- , tc == funTyCon
- = go vis env arg arg' <!> go vis env res res'
+ eqFunTy :: RnEnv2 -> Type -> Type -> Type -> Bool
+ -- Last arg is /not/ FunTy
+ eqFunTy env arg res ty@(AppTy{}) = get_args ty []
where
- get_args :: Type -> [Type] -> Maybe (TyCon, [Type])
+ get_args :: Type -> [Type] -> Bool
get_args (AppTy f x) args = get_args f (x:args)
get_args (CastTy t _) args = get_args t args
- get_args (TyConApp tc tys) args = Just (tc, tys ++ args)
- get_args _ _ = Nothing
- eqFunTy vis _ _ _ _
- = Just vis
+ get_args (TyConApp tc tys) args
+ | tc == funTyCon
+ , [_, _, arg', res'] <- tys ++ args
+ = go env arg arg' && go env res res'
+ get_args _ _ = False
+ eqFunTy _ _ _ _ = False
--- | Like 'pickyEqTypeVis', but returns a Bool for convenience
-pickyEqType :: TcType -> TcType -> Bool
--- Check when two types _look_ the same, _including_ synonyms.
--- So (pickyEqType String [Char]) returns False
--- This ignores kinds and coercions, because this is used only for printing.
-pickyEqType ty1 ty2
- = isNothing $
- tc_eq_type (const Nothing) ty1 ty2
{- *********************************************************************
* *
@@ -1972,7 +1952,7 @@ boxEqPred eq_rel ty1 ty2
where
k1 = tcTypeKind ty1
k2 = tcTypeKind ty2
- homo_kind = k1 `tcEqType` k2
+ homo_kind = k1 `tcEqType` k2 -- Constraints here are inert, so tcEqType is fine
pickCapturedPreds
:: TyVarSet -- Quantifying over these