summaryrefslogtreecommitdiff
path: root/compiler/typecheck/TcUnify.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/typecheck/TcUnify.hs')
-rw-r--r--compiler/typecheck/TcUnify.hs449
1 files changed, 287 insertions, 162 deletions
diff --git a/compiler/typecheck/TcUnify.hs b/compiler/typecheck/TcUnify.hs
index a548e8d86a..8d0f79708a 100644
--- a/compiler/typecheck/TcUnify.hs
+++ b/compiler/typecheck/TcUnify.hs
@@ -10,14 +10,14 @@ Type subsumption and unification
module TcUnify (
-- Full-blown subsumption
- tcWrapResult, tcWrapResultO, tcSkolemise,
- tcSubTypeHR, tcSubType, tcSubType_NC, tcSubTypeDS, tcSubTypeDS_O,
- tcSubTypeDS_NC, tcSubTypeDS_NC_O,
+ tcWrapResult, tcWrapResultO, tcSkolemise, tcSkolemiseET,
+ tcSubTypeHR, tcSubType, tcSubTypeO, tcSubType_NC, tcSubTypeDS, tcSubTypeDS_O,
+ tcSubTypeDS_NC, tcSubTypeDS_NC_O, tcSubTypeET, tcSubTypeET_NC,
checkConstraints, buildImplication, buildImplicationFor,
-- Various unifications
unifyType_, unifyType, unifyTheta, unifyKind, noThing,
- uType,
+ uType, unifyExpType,
--------------------------------
-- Holes
@@ -61,6 +61,7 @@ import Outputable
import FastString
import Control.Monad
+import Control.Arrow ( second )
{-
************************************************************************
@@ -103,78 +104,117 @@ namely:
A function definition
An operator section
+This function must be written CPS'd because it needs to fill in the
+ExpTypes produced for arguments before it can fill in the ExpType
+passed in.
+
-}
-- Use this one when you have an "expected" type.
matchExpectedFunTys :: SDoc -- See Note [Herald for matchExpectedFunTys]
-> Arity
- -> TcSigmaType -- deeply skolemised
- -> TcM (HsWrapper, [TcSigmaType], TcSigmaType)
--- If matchExpectedFunTys n ty = (wrap, [t1,..,tn], ty_r)
--- then wrap : (t1 -> ... -> tn -> ty_r) "->" ty
-
--- This function is always called with a deeply skolemised expected result
--- type. This means that matchActualFunTys will never actually instantiate,
--- and the returned HsWrapper will be reversible (that is, just a coercion).
--- So we just piggyback on matchActualFunTys. This is just a bit dodgy, but
--- it's much better than duplicating all the logic in matchActualFunTys.
--- To keep expected/actual working out properly, we tell matchActualFunTys
--- to swap the arguments to unifyType.
-matchExpectedFunTys herald arity ty
- = ASSERT( is_deeply_skolemised ty )
- do { (wrap, arg_tys, res_ty)
- <- match_fun_tys True herald
- (Shouldn'tHappenOrigin "matchExpectedFunTys")
- arity ty [] arity
- ; return $
- case symWrapper_maybe wrap of
- Just wrap' -> (wrap', arg_tys, res_ty)
- Nothing -> pprPanic "matchExpectedFunTys" (ppr wrap $$ ppr ty) }
+ -> ExpRhoType -- deeply skolemised
+ -> ([ExpSigmaType] -> ExpRhoType -> TcM a)
+ -- must fill in these ExpTypes here
+ -> TcM (a, HsWrapper)
+-- If matchExpectedFunTys n ty = (_, wrap)
+-- then wrap : (t1 -> ... -> tn -> ty_r) "->" ty,
+-- where [t1, ..., tn], ty_r are passed to the thing_inside
+matchExpectedFunTys herald arity orig_ty thing_inside
+ = case orig_ty of
+ Check ty -> go [] arity ty
+ _ -> defer [] arity orig_ty
where
- is_deeply_skolemised (TyVarTy {}) = True
- is_deeply_skolemised (AppTy {}) = True
- is_deeply_skolemised (TyConApp {}) = True
- is_deeply_skolemised (LitTy {}) = True
- is_deeply_skolemised (CastTy ty _) = is_deeply_skolemised ty
- is_deeply_skolemised (CoercionTy {}) = True
+ go acc_arg_tys 0 ty
+ = do { result <- thing_inside (reverse acc_arg_tys) (mkCheckExpType ty)
+ ; return (result, idHsWrapper) }
+
+ go acc_arg_tys n ty
+ | Just ty' <- coreView ty = go acc_arg_tys n ty'
+
+ go acc_arg_tys n (ForAllTy (Anon arg_ty) res_ty)
+ = ASSERT( not (isPredTy arg_ty) )
+ do { (result, wrap_res) <- go (mkCheckExpType arg_ty : acc_arg_tys)
+ (n-1) res_ty
+ ; return ( result
+ , mkWpFun idHsWrapper wrap_res arg_ty res_ty ) }
+
+ go acc_arg_tys n ty@(TyVarTy tv)
+ | ASSERT( isTcTyVar tv) isMetaTyVar tv
+ = do { cts <- readMetaTyVar tv
+ ; case cts of
+ Indirect ty' -> go acc_arg_tys n ty'
+ Flexi -> defer acc_arg_tys n (mkCheckExpType ty) }
+
+ -- In all other cases we bale out into ordinary unification
+ -- However unlike the meta-tyvar case, we are sure that the
+ -- number of arguments doesn't match arity of the original
+ -- type, so we can add a bit more context to the error message
+ -- (cf Trac #7869).
+ --
+ -- It is not always an error, because specialized type may have
+ -- different arity, for example:
+ --
+ -- > f1 = f2 'a'
+ -- > f2 :: Monad m => m Bool
+ -- > f2 = undefined
+ --
+ -- But in that case we add specialized type into error context
+ -- anyway, because it may be useful. See also Trac #9605.
+ go acc_arg_tys n ty = addErrCtxtM mk_ctxt $
+ defer acc_arg_tys n (mkCheckExpType ty)
+
+ ------------
+ defer acc_arg_tys n fun_ty
+ = do { more_arg_tys <- replicateM n newOpenInferExpType
+ ; res_ty <- newOpenInferExpType
+ ; result <- thing_inside (reverse acc_arg_tys ++ more_arg_tys) res_ty
+ ; more_arg_tys <- mapM readExpType more_arg_tys
+ ; res_ty <- readExpType res_ty
+ ; let unif_fun_ty = mkFunTys more_arg_tys res_ty
+ ; wrap <- tcSubTypeDS GenSigCtxt noThing unif_fun_ty fun_ty
+ ; return (result, wrap) }
- is_deeply_skolemised (ForAllTy (Anon _) res) = is_deeply_skolemised res
- is_deeply_skolemised (ForAllTy (Named {}) _) = False
+ ------------
+ mk_ctxt :: TidyEnv -> TcM (TidyEnv, MsgDoc)
+ mk_ctxt env = do { (env', ty) <- zonkTidyTcType env orig_tc_ty
+ ; let (args, _) = tcSplitFunTys ty
+ n_actual = length args
+ (env'', orig_ty') = tidyOpenType env' orig_tc_ty
+ ; return ( env''
+ , mk_fun_tys_msg orig_ty' ty n_actual arity herald) }
+ where
+ orig_tc_ty = checkingExpType "matchExpectedFunTys" orig_ty
+ -- this is safe b/c we're called from "go"
-matchActualFunTys :: SDoc -- See Note [Herald for matchExpectedFunTys]
+-- Like 'matchExpectedFunTys', but used when you have an "actual" type,
+-- for example in function application
+matchActualFunTys :: Outputable a
+ => SDoc -- See Note [Herald for matchExpectedFunTys]
-> CtOrigin
+ -> Maybe a -- the thing with type TcSigmaType
-> Arity
-> TcSigmaType
-> TcM (HsWrapper, [TcSigmaType], TcSigmaType)
-matchActualFunTys herald ct_orig arity ty
- = matchActualFunTysPart herald ct_orig arity ty [] arity
+-- If matchActualFunTys n ty = (wrap, [t1,..,tn], ty_r)
+-- then wrap : ty "->" (t1 -> ... -> tn -> ty_r)
+matchActualFunTys herald ct_orig mb_thing arity ty
+ = matchActualFunTysPart herald ct_orig mb_thing arity ty [] arity
-- | Variant of 'matchActualFunTys' that works when supplied only part
-- (that is, to the right of some arrows) of the full function type
-matchActualFunTysPart :: SDoc -- See Note [Herald for matchExpectedFunTys]
+matchActualFunTysPart :: Outputable a
+ => SDoc -- See Note [Herald for matchExpectedFunTys]
-> CtOrigin
+ -> Maybe a -- the thing with type TcSigmaType
-> Arity
-> TcSigmaType
-> [TcSigmaType] -- reversed args. See (*) below.
-> Arity -- overall arity of the function, for errs
-> TcM (HsWrapper, [TcSigmaType], TcSigmaType)
-matchActualFunTysPart = match_fun_tys False
-
-match_fun_tys :: Bool -- True <=> swap the args when unifying,
- -- for better expected/actual in error messages;
- -- see comments with matchExpectedFunTys
- -> SDoc
- -> CtOrigin
- -> Arity
- -> TcSigmaType
- -> [TcSigmaType]
- -> Arity
- -> TcM (HsWrapper, [TcSigmaType], TcSigmaType)
-match_fun_tys swap_tys herald ct_orig arity orig_ty orig_old_args full_arity
+matchActualFunTysPart herald ct_orig mb_thing arity orig_ty
+ orig_old_args full_arity
= go arity orig_old_args orig_ty
--- If matchActualFunTys n ty = (wrap, [t1,..,tn], ty_r)
--- then wrap : ty "->" (t1 -> ... -> tn -> ty_r)
---
-- Does not allocate unnecessary meta variables: if the input already is
-- a function, we just take it apart. Not only is this efficient,
-- it's important for higher rank: the argument might be of form
@@ -221,15 +261,15 @@ match_fun_tys swap_tys herald ct_orig arity orig_ty orig_old_args full_arity
go n acc_args (ForAllTy (Anon arg_ty) res_ty)
= ASSERT( not (isPredTy arg_ty) )
do { (wrap_res, tys, ty_r) <- go (n-1) (arg_ty : acc_args) res_ty
- ; return ( mkWpFun idHsWrapper wrap_res arg_ty (mkFunTys tys ty_r)
- , arg_ty:tys, ty_r ) }
+ ; return ( mkWpFun idHsWrapper wrap_res arg_ty ty_r
+ , arg_ty : tys, ty_r ) }
go n acc_args ty@(TyVarTy tv)
| ASSERT( isTcTyVar tv) isMetaTyVar tv
= do { cts <- readMetaTyVar tv
; case cts of
Indirect ty' -> go n acc_args ty'
- Flexi -> defer n ty (isReturnTyVar tv) }
+ Flexi -> defer n ty }
-- In all other cases we bale out into ordinary unification
-- However unlike the meta-tyvar case, we are sure that the
@@ -247,25 +287,15 @@ match_fun_tys swap_tys herald ct_orig arity orig_ty orig_old_args full_arity
-- But in that case we add specialized type into error context
-- anyway, because it may be useful. See also Trac #9605.
go n acc_args ty = addErrCtxtM (mk_ctxt (reverse acc_args) ty) $
- defer n ty False
+ defer n ty
------------
- -- If we decide that a ReturnTv (see Note [ReturnTv] in TcType) should
- -- really be a function type, then we need to allow the
- -- result types also to be a ReturnTv.
- defer n fun_ty is_return
- = do { arg_tys <- replicateM n new_flexi
- ; res_ty <- new_flexi
+ defer n fun_ty
+ = do { arg_tys <- replicateM n newOpenFlexiTyVarTy
+ ; res_ty <- newOpenFlexiTyVarTy
; let unif_fun_ty = mkFunTys arg_tys res_ty
- ; co <- if swap_tys
- then mkTcSymCo <$> unifyType noThing unif_fun_ty fun_ty
- else unifyType noThing fun_ty unif_fun_ty
+ ; co <- unifyType mb_thing fun_ty unif_fun_ty
; return (mkWpCastN co, arg_tys, res_ty) }
- where
- -- preserve ReturnTv-ness
- new_flexi :: TcM TcType
- new_flexi | is_return = (mkTyVarTy . fst) <$> newOpenReturnTyVar
- | otherwise = newOpenFlexiTyVarTy
------------
mk_ctxt :: [TcSigmaType] -> TcSigmaType -> TidyEnv -> TcM (TidyEnv, MsgDoc)
@@ -276,17 +306,24 @@ match_fun_tys swap_tys herald ct_orig arity orig_ty orig_old_args full_arity
; let (zonked_args, _) = tcSplitFunTys zonked
n_actual = length zonked_args
(env2, unzonked) = tidyOpenType env1 ty
- ; return (env2, mk_msg unzonked zonked n_actual) }
-
- mk_msg full_ty ty n_args
- = herald <+> speakNOf full_arity (text "argument") <> comma $$
- if n_args == full_arity
- then text "its type is" <+> quotes (pprType full_ty) <>
- comma $$
- text "it is specialized to" <+> quotes (pprType ty)
- else sep [text "but its type" <+> quotes (pprType ty),
- if n_args == 0 then text "has none"
- else text "has only" <+> speakN n_args]
+ ; return ( env2
+ , mk_fun_tys_msg unzonked zonked n_actual full_arity herald) }
+
+mk_fun_tys_msg :: TcType -- the full type passed in (unzonked)
+ -> TcType -- the full type passed in (zonked)
+ -> Arity -- the # of args found
+ -> Arity -- the # of args wanted
+ -> SDoc -- overall herald
+ -> SDoc
+mk_fun_tys_msg full_ty ty n_args full_arity herald
+ = herald <+> speakNOf full_arity (text "argument") <> comma $$
+ if n_args == full_arity
+ then text "its type is" <+> quotes (pprType full_ty) <>
+ comma $$
+ text "it is specialized to" <+> quotes (pprType ty)
+ else sep [text "but its type" <+> quotes (pprType ty),
+ if n_args == 0 then text "has none"
+ else text "has only" <+> speakN n_args]
----------------------
matchExpectedListTy :: TcRhoType -> TcM (TcCoercionN, TcRhoType)
@@ -486,28 +523,66 @@ skolemising the type.
tcSubTypeHR :: Outputable a
=> CtOrigin -- ^ of the actual type
-> Maybe a -- ^ If present, it has type ty_actual
- -> TcSigmaType -> TcRhoType -> TcM HsWrapper
+ -> TcSigmaType -> ExpRhoType -> TcM HsWrapper
tcSubTypeHR orig = tcSubTypeDS_NC_O orig GenSigCtxt
tcSubType :: Outputable a
=> UserTypeCtxt -> Maybe a -- ^ If present, it has type ty_actual
- -> TcSigmaType -> TcSigmaType -> TcM HsWrapper
+ -> TcSigmaType -> ExpSigmaType -> TcM HsWrapper
-- Checks that actual <= expected
-- Returns HsWrapper :: actual ~ expected
tcSubType ctxt maybe_thing ty_actual ty_expected
- = addSubTypeCtxt ty_actual ty_expected $
- do { traceTc "tcSubType" (vcat [ pprUserTypeCtxt ctxt
- , ppr maybe_thing
- , ppr ty_actual
- , ppr ty_expected ])
- ; tc_sub_type origin origin ctxt ty_actual ty_expected }
+ = tcSubTypeO origin ctxt ty_actual ty_expected
where
origin = TypeEqOrigin { uo_actual = ty_actual
, uo_expected = ty_expected
, uo_thing = mkErrorThing <$> maybe_thing }
+
+-- | This is like 'tcSubType' but accepts an 'ExpType' as the /actual/ type.
+-- You probably want this only when looking at patterns, never expressions.
+tcSubTypeET :: CtOrigin -> ExpSigmaType -> TcSigmaType -> TcM HsWrapper
+tcSubTypeET orig ty_actual ty_expected
+ = uExpTypeX orig ty_expected ty_actual
+ (return . mkWpCastN . mkTcSymCo)
+ (\ty_a -> tcSubTypeO orig GenSigCtxt ty_a
+ (mkCheckExpType ty_expected))
+
+-- | This is like 'tcSubType' but accepts an 'ExpType' as the /actual/ type.
+-- You probably want this only when looking at patterns, never expressions.
+-- Does not add context.
+tcSubTypeET_NC :: UserTypeCtxt -> ExpSigmaType -> TcSigmaType -> TcM HsWrapper
+tcSubTypeET_NC _ ty_actual@(Infer {}) ty_expected
+ = mkWpCastN . mkTcSymCo <$> unifyExpType noThing ty_expected ty_actual
+tcSubTypeET_NC ctxt (Check ty_actual) ty_expected
+ = tc_sub_type orig orig ctxt ty_actual ty_expected'
+ where
+ ty_expected' = mkCheckExpType ty_expected
+ orig = TypeEqOrigin { uo_actual = ty_actual
+ , uo_expected = ty_expected'
+ , uo_thing = Nothing }
+
+tcSubTypeO :: CtOrigin -- ^ of the actual type
+ -> UserTypeCtxt -- ^ of the expected type
+ -> TcSigmaType
+ -> ExpSigmaType
+ -> TcM HsWrapper
+tcSubTypeO origin ctxt ty_actual ty_expected
+ = addSubTypeCtxt ty_actual ty_expected $
+ do { traceTc "tcSubType" (vcat [ pprCtOrigin origin
+ , pprUserTypeCtxt ctxt
+ , ppr ty_actual
+ , ppr ty_expected ])
+ ; tc_sub_type eq_orig origin ctxt ty_actual ty_expected }
+ where
+ eq_orig | TypeEqOrigin {} <- origin = origin
+ | otherwise
+ = TypeEqOrigin { uo_actual = ty_actual
+ , uo_expected = ty_expected
+ , uo_thing = Nothing }
+
tcSubTypeDS :: Outputable a => UserTypeCtxt -> Maybe a -- ^ has type ty_actual
- -> TcSigmaType -> TcRhoType -> TcM HsWrapper
+ -> TcSigmaType -> ExpRhoType -> TcM HsWrapper
-- Just like tcSubType, but with the additional precondition that
-- ty_expected is deeply skolemised (hence "DS")
tcSubTypeDS ctxt m_expr ty_actual ty_expected
@@ -518,7 +593,7 @@ tcSubTypeDS ctxt m_expr ty_actual ty_expected
-- the "actual" type
tcSubTypeDS_O :: Outputable a
=> CtOrigin -> UserTypeCtxt
- -> Maybe a -> TcSigmaType -> TcRhoType
+ -> Maybe a -> TcSigmaType -> ExpRhoType
-> TcM HsWrapper
tcSubTypeDS_O orig ctxt maybe_thing ty_actual ty_expected
= addSubTypeCtxt ty_actual ty_expected $
@@ -528,16 +603,23 @@ tcSubTypeDS_O orig ctxt maybe_thing ty_actual ty_expected
, ppr ty_expected ])
; tcSubTypeDS_NC_O orig ctxt maybe_thing ty_actual ty_expected }
-addSubTypeCtxt :: TcType -> TcType -> TcM a -> TcM a
+addSubTypeCtxt :: TcType -> ExpType -> TcM a -> TcM a
addSubTypeCtxt ty_actual ty_expected thing_inside
- | isRhoTy ty_actual -- If there is no polymorphism involved, the
- , isRhoTy ty_expected -- TypeEqOrigin stuff (added by the _NC functions)
- = thing_inside -- gives enough context by itself
+ | isRhoTy ty_actual -- If there is no polymorphism involved, the
+ , isRhoExpTy ty_expected -- TypeEqOrigin stuff (added by the _NC functions)
+ = thing_inside -- gives enough context by itself
| otherwise
= addErrCtxtM mk_msg thing_inside
where
mk_msg tidy_env
= do { (tidy_env, ty_actual) <- zonkTidyTcType tidy_env ty_actual
+ -- might not be filled if we're debugging. ugh.
+ ; mb_ty_expected <- readExpType_maybe ty_expected
+ ; (tidy_env, ty_expected) <- case mb_ty_expected of
+ Just ty -> second mkCheckExpType <$>
+ zonkTidyTcType tidy_env ty
+ Nothing -> return (tidy_env, ty_expected)
+ ; ty_expected <- readExpType ty_expected
; (tidy_env, ty_expected) <- zonkTidyTcType tidy_env ty_expected
; let msg = vcat [ hang (text "When checking that:")
4 (ppr ty_actual)
@@ -549,7 +631,7 @@ addSubTypeCtxt ty_actual ty_expected thing_inside
-- The "_NC" variants do not add a typechecker-error context;
-- the caller is assumed to do that
-tcSubType_NC :: UserTypeCtxt -> TcSigmaType -> TcSigmaType -> TcM HsWrapper
+tcSubType_NC :: UserTypeCtxt -> TcSigmaType -> ExpSigmaType -> TcM HsWrapper
tcSubType_NC ctxt ty_actual ty_expected
= do { traceTc "tcSubType_NC" (vcat [pprUserTypeCtxt ctxt, ppr ty_actual, ppr ty_expected])
; tc_sub_type origin origin ctxt ty_actual ty_expected }
@@ -561,7 +643,7 @@ tcSubType_NC ctxt ty_actual ty_expected
tcSubTypeDS_NC :: Outputable a
=> UserTypeCtxt
-> Maybe a -- ^ If present, this has type ty_actual
- -> TcSigmaType -> TcRhoType -> TcM HsWrapper
+ -> TcSigmaType -> ExpRhoType -> TcM HsWrapper
tcSubTypeDS_NC ctxt maybe_thing ty_actual ty_expected
= do { traceTc "tcSubTypeDS_NC" (vcat [pprUserTypeCtxt ctxt, ppr ty_actual, ppr ty_expected])
; tcSubTypeDS_NC_O origin ctxt maybe_thing ty_actual ty_expected }
@@ -574,25 +656,35 @@ tcSubTypeDS_NC_O :: Outputable a
=> CtOrigin -- origin used for instantiation only
-> UserTypeCtxt
-> Maybe a
- -> TcSigmaType -> TcRhoType -> TcM HsWrapper
+ -> TcSigmaType -> ExpRhoType -> TcM HsWrapper
-- Just like tcSubType, but with the additional precondition that
-- ty_expected is deeply skolemised
-tcSubTypeDS_NC_O inst_orig ctxt m_thing ty_actual ty_expected
- = tc_sub_type_ds eq_orig inst_orig ctxt ty_actual ty_expected
+tcSubTypeDS_NC_O inst_orig ctxt m_thing ty_actual et
+ = uExpTypeX eq_orig ty_actual et
+ (return . mkWpCastN)
+ (tc_sub_type_ds eq_orig inst_orig ctxt ty_actual)
where
- eq_orig = TypeEqOrigin { uo_actual = ty_actual, uo_expected = ty_expected
- , uo_thing = mkErrorThing <$> m_thing}
+ eq_orig = TypeEqOrigin { uo_actual = ty_actual, uo_expected = et
+ , uo_thing = mkErrorThing <$> m_thing }
---------------
tc_sub_type :: CtOrigin -- origin used when calling uType
-> CtOrigin -- origin used when instantiating
- -> UserTypeCtxt -> TcSigmaType -> TcSigmaType -> TcM HsWrapper
-tc_sub_type eq_orig inst_orig ctxt ty_actual ty_expected
+ -> UserTypeCtxt -> TcSigmaType -> ExpSigmaType -> TcM HsWrapper
+tc_sub_type eq_orig inst_orig ctxt ty_actual et
+ = uExpTypeX eq_orig ty_actual et
+ (return . mkWpCastN)
+ (tc_sub_tc_type eq_orig inst_orig ctxt ty_actual)
+
+tc_sub_tc_type :: CtOrigin -- used when calling uType
+ -> CtOrigin -- used when instantiating
+ -> UserTypeCtxt -> TcSigmaType -> TcSigmaType -> TcM HsWrapper
+tc_sub_tc_type eq_orig inst_orig ctxt ty_actual ty_expected
| Just tv_actual <- tcGetTyVar_maybe ty_actual -- See Note [Higher rank types]
= do { lookup_res <- lookupTcTyVar tv_actual
; case lookup_res of
- Filled ty_actual' -> tc_sub_type eq_orig inst_orig
- ctxt ty_actual' ty_expected
+ Filled ty_actual' -> tc_sub_tc_type eq_orig inst_orig
+ ctxt ty_actual' ty_expected
-- It's tempting to see if tv_actual can unify with a polytype
-- and, if so, call uType; otherwise, skolemise first. But this
@@ -641,7 +733,7 @@ tc_sub_type_ds eq_orig inst_orig ctxt ty_actual ty_expected
Filled ty_e' ->
do { traceTc "tcSubTypeDS_NC_O following filled exp meta-tyvar:"
(ppr tv_e <+> text "-->" <+> ppr ty_e')
- ; tc_sub_type eq_orig inst_orig ctxt ty_a ty_e' }
+ ; tc_sub_tc_type eq_orig inst_orig ctxt ty_a ty_e' }
Unfilled details
| canUnifyWithPolyType dflags details
&& isTouchableMetaTyVar tclvl tv_e -- don't want skolems here
@@ -660,8 +752,10 @@ tc_sub_type_ds eq_orig inst_orig ctxt ty_actual ty_expected
= -- See Note [Co/contra-variance of subsumption checking]
do { res_wrap <- tc_sub_type_ds eq_orig inst_orig ctxt act_res exp_res
; arg_wrap
- <- tc_sub_type eq_orig (GivenOrigin (SigSkol GenSigCtxt exp_arg))
- ctxt exp_arg act_arg
+ <- tc_sub_tc_type eq_orig (GivenOrigin
+ (SigSkol GenSigCtxt
+ (mkCheckExpType exp_arg)))
+ ctxt exp_arg act_arg
; return (mkWpFun arg_wrap res_wrap exp_arg exp_res) }
-- arg_wrap :: exp_arg ~ act_arg
-- res_wrap :: act-res ~ exp_res
@@ -670,7 +764,11 @@ tc_sub_type_ds eq_orig inst_orig ctxt ty_actual ty_expected
| let (tvs, theta, _) = tcSplitSigmaTy ty_a
, not (null tvs && null theta)
= do { (in_wrap, in_rho) <- topInstantiate inst_orig ty_a
- ; body_wrap <- tcSubTypeDS_NC_O inst_orig ctxt noThing in_rho ty_e
+ ; body_wrap <- tc_sub_type_ds
+ (eq_orig { uo_actual = in_rho
+ , uo_expected =
+ mkCheckExpType ty_expected })
+ inst_orig ctxt in_rho ty_e
; return (body_wrap <.> in_wrap) }
| otherwise -- Revert to unification
@@ -706,13 +804,13 @@ tc_sub_type_ds eq_orig inst_orig ctxt ty_actual ty_expected
-----------------
-- needs both un-type-checked (for origins) and type-checked (for wrapping)
-- expressions
-tcWrapResult :: HsExpr Name -> HsExpr TcId -> TcSigmaType -> TcRhoType
+tcWrapResult :: HsExpr Name -> HsExpr TcId -> TcSigmaType -> ExpRhoType
-> TcM (HsExpr TcId)
tcWrapResult rn_expr = tcWrapResultO (exprCtOrigin rn_expr)
-- | Sometimes we don't have a @HsExpr Name@ to hand, and this is more
-- convenient.
-tcWrapResultO :: CtOrigin -> HsExpr TcId -> TcSigmaType -> TcRhoType
+tcWrapResultO :: CtOrigin -> HsExpr TcId -> TcSigmaType -> ExpRhoType
-> TcM (HsExpr TcId)
tcWrapResultO orig expr actual_ty res_ty
= do { traceTc "tcWrapResult" (vcat [ text "Actual: " <+> ppr actual_ty
@@ -736,21 +834,14 @@ wrapFunResCoercion arg_tys co_fn_res
; return (mkWpLams arg_ids <.> co_fn_res <.> mkWpEvVarApps arg_ids) }
-----------------------------------
--- | Infer a type using a type "checking" function by passing in a ReturnTv,
--- which can unify with *anything*. See also Note [ReturnTv] in TcType
-tcInfer :: (TcType -> TcM a) -> TcM (a, TcType)
+-- | Infer a type using a fresh ExpType
+-- See also Note [ExpType] in TcMType
+tcInfer :: (ExpRhoType -> TcM a) -> TcM (a, TcType)
tcInfer tc_check
- = do { (ret_tv, ret_kind) <- newOpenReturnTyVar
- ; res <- tc_check (mkTyVarTy ret_tv)
- ; details <- readMetaTyVar ret_tv
- ; res_ty <- case details of
- Indirect ty -> return ty
- Flexi -> -- Checking was uninformative
- do { traceTc "Defaulting un-filled ReturnTv to a TauTv" (ppr ret_tv)
- ; tau_ty <- newFlexiTyVarTy ret_kind
- ; writeMetaTyVar ret_tv tau_ty
- ; return tau_ty }
- ; return (res, res_ty) }
+ = do { res_ty <- newOpenInferExpType
+ ; result <- tc_check res_ty
+ ; res_ty <- readExpType res_ty
+ ; return (result, res_ty) }
{-
************************************************************************
@@ -765,9 +856,7 @@ tcInfer tc_check
-- The returned 'HsWrapper' has type @specific_ty -> expected_ty@.
tcSkolemise :: UserTypeCtxt -> TcSigmaType
-> ([TcTyVar] -> TcType -> TcM result)
- -- ^ thing_inside is passed only the *type* variables, not
- -- *coercion* variables. They are only ever used for scoped type
- -- variables.
+ -- ^ These are only ever used for scoped type variables.
-> TcM (HsWrapper, result)
-- ^ The expression has type: spec_ty -> expected_ty
@@ -801,7 +890,8 @@ tcSkolemise ctxt expected_ty thing_inside
-- Use the *instantiated* type in the SkolemInfo
-- so that the names of displayed type variables line up
- ; let skol_info = SigSkol ctxt (mkFunTys (map varType given) rho')
+ ; let skol_info = SigSkol ctxt (mkCheckExpType $
+ mkFunTys (map varType given) rho')
; (ev_binds, result) <- checkConstraints skol_info tvs' given $
thing_inside tvs' rho'
@@ -810,6 +900,15 @@ tcSkolemise ctxt expected_ty thing_inside
-- The ev_binds returned by checkConstraints is very
-- often empty, in which case mkWpLet is a no-op
+-- | Variant of 'tcSkolemise' that takes an ExpType
+tcSkolemiseET :: UserTypeCtxt -> ExpSigmaType
+ -> (ExpRhoType -> TcM result)
+ -> TcM (HsWrapper, result)
+tcSkolemiseET _ et@(Infer {}) thing_inside
+ = (idHsWrapper, ) <$> thing_inside et
+tcSkolemiseET ctxt (Check ty) thing_inside
+ = tcSkolemise ctxt ty $ \_ -> thing_inside . mkCheckExpType
+
checkConstraints :: SkolemInfo
-> [TcTyVar] -- Skolems
-> [EvVar] -- Given
@@ -893,32 +992,42 @@ unifyType_ :: Outputable a => Maybe a -- ^ If present, has type 'ty1'
unifyType_ thing ty1 ty2 = void $ unifyType thing ty1 ty2
unifyType :: Outputable a => Maybe a -- ^ If present, has type 'ty1'
- -> TcTauType -> TcTauType -> TcM TcCoercion
+ -> TcTauType -> TcTauType -> TcM TcCoercionN
-- Actual and expected types
-- Returns a coercion : ty1 ~ ty2
unifyType thing ty1 ty2 = uType origin TypeLevel ty1 ty2
where
- origin = TypeEqOrigin { uo_actual = ty1, uo_expected = ty2
+ origin = TypeEqOrigin { uo_actual = ty1, uo_expected = mkCheckExpType ty2
, uo_thing = mkErrorThing <$> thing }
+-- | Variant of 'unifyType' that takes an 'ExpType' as its second type
+unifyExpType :: Outputable a => Maybe a
+ -> TcTauType -> ExpType -> TcM TcCoercionN
+unifyExpType mb_thing ty1 ty2
+ = uExpType ty_orig ty1 ty2
+ where
+ ty_orig = TypeEqOrigin { uo_actual = ty1
+ , uo_expected = ty2
+ , uo_thing = mkErrorThing <$> mb_thing }
+
-- | Use this instead of 'Nothing' when calling 'unifyType' without
-- a good "thing" (where the "thing" has the "actual" type passed in)
-- This has an 'Outputable' instance, avoiding amgiguity problems.
noThing :: Maybe (HsExpr Name)
noThing = Nothing
-unifyKind :: Outputable a => Maybe a -> TcKind -> TcKind -> TcM Coercion
+unifyKind :: Outputable a => Maybe a -> TcKind -> TcKind -> TcM CoercionN
unifyKind thing ty1 ty2 = uType origin KindLevel ty1 ty2
- where origin = TypeEqOrigin { uo_actual = ty1, uo_expected = ty2
+ where origin = TypeEqOrigin { uo_actual = ty1, uo_expected = mkCheckExpType ty2
, uo_thing = mkErrorThing <$> thing }
---------------
-unifyPred :: PredType -> PredType -> TcM TcCoercion
+unifyPred :: PredType -> PredType -> TcM TcCoercionN
-- Actual and expected types
unifyPred = unifyType noThing
---------------
-unifyTheta :: TcThetaType -> TcThetaType -> TcM [TcCoercion]
+unifyTheta :: TcThetaType -> TcThetaType -> TcM [TcCoercionN]
-- Actual and expected types
unifyTheta theta1 theta2
= do { checkTc (equalLength theta1 theta2)
@@ -936,6 +1045,33 @@ unifyTheta theta1 theta2
uType is the heart of the unifier.
-}
+uExpType :: CtOrigin -> TcType -> ExpType -> TcM CoercionN
+uExpType orig ty1 et
+ = uExpTypeX orig ty1 et return $
+ uType orig TypeLevel ty1
+
+-- | Tries to unify with an ExpType. If the ExpType is filled in, calls the first
+-- continuation with the produced coercion. Otherwise, calls the second
+-- continuation. This can happen either with a Check or with an untouchable
+-- ExpType that reverts to a tau-type. See Note [TcLevel of ExpType]
+uExpTypeX :: CtOrigin -> TcType -> ExpType
+ -> (TcCoercionN -> TcM a) -- Infer case, co :: TcType ~N ExpType
+ -> (TcType -> TcM a) -- Check / untouchable case
+ -> TcM a
+uExpTypeX orig ty1 et@(Infer _ tc_lvl ki _) coercion_cont type_cont
+ = do { cur_lvl <- getTcLevel
+ ; if cur_lvl `sameDepthAs` tc_lvl
+ then do { ki_co <- uType kind_orig KindLevel (typeKind ty1) ki
+ ; writeExpType et (ty1 `mkCastTy` ki_co)
+ ; coercion_cont $ mkTcNomReflCo ty1 `mkTcCoherenceRightCo` ki_co }
+ else do { traceTc "Preventing writing to untouchable ExpType" empty
+ ; tau <- expTypeToType et -- See Note [TcLevel of ExpType]
+ ; type_cont tau }}
+ where
+ kind_orig = KindEqOrigin ty1 Nothing orig (Just TypeLevel)
+uExpTypeX _ _ (Check ty2) _ type_cont
+ = type_cont ty2
+
------------
uType, uType_defer
:: CtOrigin
@@ -1076,7 +1212,8 @@ uType origin t_or_k orig_ty1 orig_ty2
go (CoercionTy co1) (CoercionTy co2)
= do { let ty1 = coercionType co1
ty2 = coercionType co2
- ; kco <- uType (KindEqOrigin orig_ty1 orig_ty2 origin (Just t_or_k))
+ ; kco <- uType (KindEqOrigin orig_ty1 (Just orig_ty2) origin
+ (Just t_or_k))
KindLevel
ty1 ty2
; return $ mkProofIrrelCo Nominal kco co1 co2 }
@@ -1268,7 +1405,7 @@ uUnfilledVars origin t_or_k swapped tv1 details1 tv2 details2
k2 = tyVarKind tv2
ty1 = mkTyVarTy tv1
ty2 = mkTyVarTy tv2
- kind_origin = KindEqOrigin ty1 ty2 origin (Just t_or_k)
+ kind_origin = KindEqOrigin ty1 (Just ty2) origin (Just t_or_k)
-- | apply sym iff swapped
maybe_sym :: SwapFlag -> Coercion -> Coercion
@@ -1282,10 +1419,6 @@ nicer_to_update_tv1 _ SigTv _ = False
-- variables in preference to ones gotten (say) by
-- instantiating a polymorphic function with a user-written
-- type sig
-nicer_to_update_tv1 _ ReturnTv _ = True
-nicer_to_update_tv1 _ _ ReturnTv = False
- -- ReturnTvs are really holes just begging to be filled in.
- -- Let's oblige.
nicer_to_update_tv1 tv1 _ _ = isSystemName (Var.varName tv1)
----------------
@@ -1297,9 +1430,9 @@ checkTauTvUpdate :: DynFlags
-> TcM (Maybe ( TcType -- possibly-expanded ty
, Coercion )) -- :: k2 ~N k1
-- (checkTauTvUpdate tv ty)
--- We are about to update the TauTv/ReturnTv tv with ty.
+-- We are about to update the TauTv tv with ty.
-- Check (a) that tv doesn't occur in ty (occurs check)
--- (b) that kind(ty) is a sub-kind of kind(tv)
+-- (b) that kind(ty) matches kind(tv)
--
-- We have two possible outcomes:
-- (1) Return the type to update the type variable with,
@@ -1323,12 +1456,7 @@ checkTauTvUpdate dflags origin t_or_k tv ty
| otherwise
= do { ty <- zonkTcType ty
; co_k <- uType kind_origin KindLevel (typeKind ty) (tyVarKind tv)
- ; if | is_return_tv -> -- ReturnTv: a simple occurs-check is all that we need
- -- See Note [ReturnTv] in TcType
- if tv `elemVarSet` tyCoVarsOfType ty
- then return Nothing
- else return (Just (ty, co_k))
- | defer_me ty -> -- Quick test
+ ; if | defer_me ty -> -- Quick test
-- Failed quick test so try harder
case occurCheckExpand dflags tv ty of
OC_OK ty2 | defer_me ty2 -> return Nothing
@@ -1336,10 +1464,9 @@ checkTauTvUpdate dflags origin t_or_k tv ty
_ -> return Nothing
| otherwise -> return (Just (ty, co_k)) }
where
- kind_origin = KindEqOrigin (mkTyVarTy tv) ty origin (Just t_or_k)
+ kind_origin = KindEqOrigin (mkTyVarTy tv) (Just ty) origin (Just t_or_k)
details = tcTyVarDetails tv
info = mtv_info details
- is_return_tv = isReturnTyVar tv
impredicative = canUnifyWithPolyType dflags details
defer_me :: TcType -> Bool
@@ -1541,24 +1668,22 @@ matchExpectedFunKind num_args_remaining ty = go
= do { maybe_kind <- readMetaTyVar kvar
; case maybe_kind of
Indirect fun_kind -> go fun_kind
- Flexi -> defer (isReturnTyVar kvar) k }
+ Flexi -> defer k }
go k@(ForAllTy (Anon arg) res)
= return (mkNomReflCo k, arg, res)
- go other = defer False other
+ go other = defer other
- defer is_return k
- = do { arg_kind <- new_flexi
- ; res_kind <- new_flexi
+ defer k
+ = do { arg_kind <- newMetaKindVar
+ ; res_kind <- newMetaKindVar
; let new_fun = mkFunTy arg_kind res_kind
thing = mkTypeErrorThingArgs ty num_args_remaining
origin = TypeEqOrigin { uo_actual = k
- , uo_expected = new_fun
+ , uo_expected = mkCheckExpType new_fun
, uo_thing = Just thing
}
; co <- uType origin KindLevel k new_fun
; return (co, arg_kind, res_kind) }
where
- new_flexi | is_return = newReturnTyVarTy liftedTypeKind
- | otherwise = newMetaKindVar