diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2018-12-24 14:55:41 +0000 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2018-12-24 14:55:41 +0000 |
commit | f4449232e43784abff325bd3bf90f3cb5857b28b (patch) | |
tree | 5babde190babb2af2385d3dc5f97d20e1cac5343 | |
parent | 79d031326d614f6ca637b67a11949dab64afe728 (diff) | |
download | haskell-f4449232e43784abff325bd3bf90f3cb5857b28b.tar.gz |
Make tcTypeKind monadic
This patch is work in progress on Trac #15952.
IT DOES NOT COMPILE.
The main payload is progress towards making tcTypeKind monadic.
However I have not yet made a monadic version of tcEqType, nor
changed all those tcEqType calls to a monadic context. Hence,
it won't compile as-is.
I'm just parking the work I've done, on a branch,
until I've had a chance to agree the path with Richard.
(The previous patches on this branch /do/ compile and
almost-completely validate.)
-rw-r--r-- | compiler/typecheck/FamInst.hs | 12 | ||||
-rw-r--r-- | compiler/typecheck/Inst.hs | 29 | ||||
-rw-r--r-- | compiler/typecheck/TcCanonical.hs | 94 | ||||
-rw-r--r-- | compiler/typecheck/TcDeriv.hs | 49 | ||||
-rw-r--r-- | compiler/typecheck/TcDerivInfer.hs | 25 | ||||
-rw-r--r-- | compiler/typecheck/TcErrors.hs | 21 | ||||
-rw-r--r-- | compiler/typecheck/TcExpr.hs | 8 | ||||
-rw-r--r-- | compiler/typecheck/TcFlatten.hs | 35 | ||||
-rw-r--r-- | compiler/typecheck/TcHsSyn.hs | 10 | ||||
-rw-r--r-- | compiler/typecheck/TcHsType.hs | 31 | ||||
-rw-r--r-- | compiler/typecheck/TcInstDcls.hs | 2 | ||||
-rw-r--r-- | compiler/typecheck/TcInteract.hs | 6 | ||||
-rw-r--r-- | compiler/typecheck/TcMType.hs | 249 | ||||
-rw-r--r-- | compiler/typecheck/TcPat.hs | 3 | ||||
-rw-r--r-- | compiler/typecheck/TcPatSyn.hs | 42 | ||||
-rw-r--r-- | compiler/typecheck/TcRnDriver.hs | 9 | ||||
-rw-r--r-- | compiler/typecheck/TcSMonad.hs | 13 | ||||
-rw-r--r-- | compiler/typecheck/TcSplice.hs | 6 | ||||
-rw-r--r-- | compiler/typecheck/TcTyClsDecls.hs | 17 | ||||
-rw-r--r-- | compiler/typecheck/TcType.hs | 166 | ||||
-rw-r--r-- | compiler/typecheck/TcUnify.hs | 32 | ||||
-rw-r--r-- | compiler/types/Type.hs | 37 |
22 files changed, 551 insertions, 345 deletions
diff --git a/compiler/typecheck/FamInst.hs b/compiler/typecheck/FamInst.hs index 144b315bed..4f32065d37 100644 --- a/compiler/typecheck/FamInst.hs +++ b/compiler/typecheck/FamInst.hs @@ -155,8 +155,14 @@ newFamInst :: FamFlavor -> CoAxiom Unbranched -> TcM FamInst newFamInst flavor axiom@(CoAxiom { co_ax_tc = fam_tc }) = ASSERT2( tyCoVarsOfTypes lhs `subVarSet` tcv_set, text "lhs" <+> pp_ax ) ASSERT2( tyCoVarsOfType rhs `subVarSet` tcv_set, text "rhs" <+> pp_ax ) - ASSERT2( lhs_kind `eqType` rhs_kind, text "kind" <+> pp_ax $$ ppr lhs_kind $$ ppr rhs_kind ) - do { (subst, tvs') <- freshenTyVarBndrs tvs + do { when debugIsOn $ + do { lhs_kind <- tcTypeKindM (mkTyConApp fam_tc lhs) + ; rhs_kind <- tcTypeKindM rhs + ; ASSERT2( lhs_kind `eqType` rhs_kind, + text "kind" <+> pp_ax $$ ppr lhs_kind $$ ppr rhs_kind ) + return () } + + ; (subst, tvs') <- freshenTyVarBndrs tvs ; (subst, cvs') <- freshenCoVarBndrsX subst cvs ; dflags <- getDynFlags ; let lhs' = substTys subst lhs @@ -187,8 +193,6 @@ newFamInst flavor axiom@(CoAxiom { co_ax_tc = fam_tc }) , fi_rhs = rhs' , fi_axiom = axiom }) } where - lhs_kind = tcTypeKind (mkTyConApp fam_tc lhs) - rhs_kind = tcTypeKind rhs tcv_set = mkVarSet (tvs ++ cvs) pp_ax = pprCoAxiom axiom CoAxBranch { cab_tvs = tvs diff --git a/compiler/typecheck/Inst.hs b/compiler/typecheck/Inst.hs index dd8f8ba03c..cb49073a57 100644 --- a/compiler/typecheck/Inst.hs +++ b/compiler/typecheck/Inst.hs @@ -298,14 +298,13 @@ instTyVarsWith orig tvs tys go subst [] [] = return subst go subst (tv:tvs) (ty:tys) - | tv_kind `tcEqType` ty_kind - = go (extendTCvSubst subst tv ty) tvs tys - | otherwise - = do { co <- emitWantedEq orig KindLevel Nominal ty_kind tv_kind - ; go (extendTCvSubst subst tv (ty `mkCastTy` co)) tvs tys } - where - tv_kind = substTy subst (tyVarKind tv) - ty_kind = tcTypeKind ty + = do { let tv_kind = substTy subst (tyVarKind tv) + ; ty_kind <- tcTypeKindM ty + ; eq_kind <- tv_kind `tcEqTypeM` ty_kind + ; ty' <- if eq_kind then return ty + else do { co <- emitWantedEq orig KindLevel Nominal ty_kind tv_kind + ; return (ty `mkCastTy` co) } + ; go (extendTCvSubst subst tv ty') tvs tys } go _ _ _ = pprPanic "instTysWith" (ppr tvs $$ ppr tys) @@ -580,17 +579,17 @@ tcInstTyBinder _ subst (Anon ty) mkHEqBoxTy :: TcCoercion -> Type -> Type -> TcM Type -- monadic just for convenience with mkEqBoxTy mkHEqBoxTy co ty1 ty2 - = return $ - mkTyConApp (promoteDataCon heqDataCon) [k1, k2, ty1, ty2, mkCoercionTy co] - where k1 = tcTypeKind ty1 - k2 = tcTypeKind ty2 + = do { k1 <- tcTypeKindM ty1 + ; k2 <- tcTypeKindM ty2 + ; return $ mkTyConApp (promoteDataCon heqDataCon) + [k1, k2, ty1, ty2, mkCoercionTy co] } -- | This takes @a ~# b@ and returns @a ~ b@. mkEqBoxTy :: TcCoercion -> Type -> Type -> TcM Type mkEqBoxTy co ty1 ty2 - = return $ - mkTyConApp (promoteDataCon eqDataCon) [k, ty1, ty2, mkCoercionTy co] - where k = tcTypeKind ty1 + = do { k <- tcTypeKindM ty1 + ; return $ mkTyConApp (promoteDataCon eqDataCon) + [k, ty1, ty2, mkCoercionTy co] } {- ************************************************************************ diff --git a/compiler/typecheck/TcCanonical.hs b/compiler/typecheck/TcCanonical.hs index dce9a10aff..5d9aabeaf0 100644 --- a/compiler/typecheck/TcCanonical.hs +++ b/compiler/typecheck/TcCanonical.hs @@ -873,16 +873,17 @@ can_eq_nc' -> TcS (StopOrContinue Ct) -- Expand synonyms first; see Note [Type synonyms and canonicalization] -can_eq_nc' flat _rdr_env _envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2 - | Just ty1' <- tcView ty1 = can_eq_nc flat ev eq_rel ty1' ps_ty1 ty2 ps_ty2 - | Just ty2' <- tcView ty2 = can_eq_nc flat ev eq_rel ty1 ps_ty1 ty2' ps_ty2 +can_eq_nc' flat rdr_env envs ev eq_rel ty1 ps_ty1 ty2 ps_ty2 + | Just ty1' <- tcView ty1 = can_eq_nc' flat rdr_env envs ev eq_rel ty1' ps_ty1 ty2 ps_ty2 + | Just ty2' <- tcView ty2 = can_eq_nc' flat rdr_env envs ev eq_rel ty1 ps_ty1 ty2' ps_ty2 -- need to check for reflexivity in the ReprEq case. -- See Note [Eager reflexivity check] -- Check only when flat because the zonk_eq_types check in canEqNC takes -- care of the non-flat case. can_eq_nc' True _rdr_env _envs ev ReprEq ty1 _ ty2 _ - | ty1 `tcEqType` ty2 + | ty1 `tcEqType` ty2 -- In the flat case ty1 and ty2 are zonked, + -- so it's ok to use the non-monadic tcEqType = canEqReflexive ev ReprEq ty1 -- When working with ReprEq, unwrap newtypes. @@ -1038,17 +1039,16 @@ can_eq_nc_forall ev eq_rel s1 s2 -- This version returns the wanted constraint rather -- than putting it in the work list unify loc role ty1 ty2 - | ty1 `tcEqType` ty2 - = return (mkTcReflCo role ty1, emptyBag) - | otherwise - = do { (wanted, co) <- newWantedEq loc role ty1 ty2 - ; return (co, unitBag (mkNonCanonical wanted)) } + = do { already_eq <- ty1 `tcEqTypeM` ty2 + ; if already_eq then return (mkTcReflCo role ty1, emptyBag) + else do { (wanted, co) <- newWantedEq loc role ty1 ty2 + ; return (co, unitBag (mkNonCanonical wanted)) } } --------------------------------- -- | Compare types for equality, while zonking as necessary. Gives up -- as soon as it finds that two types are not equal. -- This is quite handy when some unification has made two --- types in an inert wanted to be equal. We can discover the equality without +-- types in an inert Wanted to be equal. We can discover the equality without -- flattening, which is sometimes very expensive (in the case of type functions). -- In particular, this function makes a ~20% improvement in test case -- perf/compiler/T5030. @@ -1304,11 +1304,13 @@ can_eq_app ev s1 t1 s2 t2 -- Test case: typecheck/should_run/Typeable1 -- We could also include this mismatch check above (for W and D), but it's slow -- and we'll get a better error message not doing it - | s1k `mismatches` s2k - = canEqHardFailure ev (s1 `mkAppTy` t1) (s2 `mkAppTy` t2) - | CtGiven { ctev_evar = evar, ctev_loc = loc } <- ev - = do { let co = mkTcCoVarCo evar + = do { s1k <- tcTypeKindM s1 + ; s2k <- tcTypeKindM s2 + ; if isForAllTy s1k /= isForAllTy s2k + then canEqHardFailure ev (s1 `mkAppTy` t1) (s2 `mkAppTy` t2) + else + do { let co = mkTcCoVarCo evar co_s = mkTcLRCo CLeft co co_t = mkTcLRCo CRight co ; evar_s <- newGivenEvVar loc ( mkTcEqPredLikeEv ev s1 s2 @@ -1316,15 +1318,7 @@ can_eq_app ev s1 t1 s2 t2 ; evar_t <- newGivenEvVar loc ( mkTcEqPredLikeEv ev t1 t2 , evCoercion co_t ) ; emitWorkNC [evar_t] - ; canEqNC evar_s NomEq s1 s2 } - - where - s1k = tcTypeKind s1 - s2k = tcTypeKind s2 - - k1 `mismatches` k2 - = isForAllTy k1 && not (isForAllTy k2) - || not (isForAllTy k1) && isForAllTy k2 + ; canEqNC evar_s NomEq s1 s2 }} ----------------------- -- | Break apart an equality over a casted type @@ -1789,10 +1783,8 @@ canCFunEqCan ev fn tys fsk else do { traceTcS "canCFunEqCan: non-refl" $ vcat [ text "Kind co:" <+> ppr kind_co , text "RHS:" <+> ppr fsk <+> dcolon <+> ppr (tyVarKind fsk) - , text "LHS:" <+> hang (ppr (mkTyConApp fn tys)) - 2 (dcolon <+> ppr (tcTypeKind (mkTyConApp fn tys))) - , text "New LHS" <+> hang (ppr new_lhs) - 2 (dcolon <+> ppr (tcTypeKind new_lhs)) ] + , text "LHS:" <+> ppr (mkTyConApp fn tys) + , text "New LHS" <+> ppr new_lhs ] ; (ev', new_co, new_fsk) <- newFlattenSkolem flav (ctEvLoc ev) fn tys' ; let xi = mkTyVarTy new_fsk `mkCastTy` kind_co @@ -1821,15 +1813,25 @@ canEqTyVar :: CtEvidence -- ev :: lhs ~ rhs -> TcType -> TcType -- rhs: already flat -> TcS (StopOrContinue Ct) canEqTyVar ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2 - | k1 `tcEqType` k2 - = canEqTyVarHomo ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2 - - -- Note [Flattening] in TcFlatten gives us (F2), which says that + = do { let k1 = tyVarKind tv1 + ; k2 <- tcTypeKindM xi2 + ; homo_kind <- tcEqTypeM k1 k2 + ; if homo_kind + then canEqTyVarHomo ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2 + else canEqTyVarTake2 ev eq_rel swapped tv1 ps_ty1 k1 xi2 ps_xi2 k2 } + +canEqTyVarTake2 :: CtEvidence -- ev :: lhs ~ rhs + -> EqRel -> SwapFlag + -> TcTyVar -> TcType -> TcKind -- tv1, its pretty form, and its kind + -> TcType -> TcType -> TcKind -- rhs, its pretty form, and its kind + -- Both tv1 and rhs are already flat + -> TcS (StopOrContinue Ct) +canEqTyVarTake2 ev eq_rel swapped tv1 ps_ty1 k1 xi2 ps_xi2 k2 + = do { -- Note [Flattening] in TcFlatten gives us (F2), which says that -- flattening is always homogeneous (doesn't change kinds). But -- perhaps by flattening the kinds of the two sides of the equality -- at hand makes them equal. So let's try that. - | otherwise - = do { (flat_k1, k1_co) <- flattenKind loc flav k1 -- k1_co :: flat_k1 ~N kind(xi1) + (flat_k1, k1_co) <- flattenKind loc flav k1 -- k1_co :: flat_k1 ~N kind(xi1) ; (flat_k2, k2_co) <- flattenKind loc flav k2 -- k2_co :: flat_k2 ~N kind(xi2) ; traceTcS "canEqTyVar tried flattening kinds" (vcat [ sep [ parens (ppr tv1 <+> dcolon <+> ppr k1) @@ -1848,7 +1850,7 @@ canEqTyVar ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2 -- See Note [Equalities with incompatible kinds] ; let role = eqRelRole eq_rel - ; if flat_k1 `tcEqType` flat_k2 + ; if flat_k1 `tcEqType` flat_k2 -- Fully zonked, so tcEqType is ok then do { let rhs_kind_co = mkTcSymCo k2_co `mkTcTransCo` k1_co -- :: kind(xi2) ~N kind(xi1) @@ -1880,10 +1882,6 @@ canEqTyVar ev eq_rel swapped tv1 ps_ty1 xi2 ps_xi2 new_rhs flat_k2 ps_rhs } } where xi1 = mkTyVarTy tv1 - - k1 = tyVarKind tv1 - k2 = tcTypeKind xi2 - loc = ctEvLoc ev flav = ctEvFlavour ev @@ -1922,7 +1920,7 @@ canEqTyVarHetero ev eq_rel tv1 co1 ki1 ps_tv1 xi2 ki2 ps_xi2 -- See Note [Equalities with incompatible kinds] | otherwise -- Wanted and Derived - -- NB: all kind equalities are Nominal + -- NB: all kind equalities are Nominal = do { emitNewDerivedEq kind_loc Nominal ki1 ki2 -- kind_ev :: (ki1 :: *) ~ (ki2 :: *) ; traceTcS "Hetero equality gives rise to derived kind equality" $ @@ -2364,7 +2362,9 @@ unifyWanted :: CtLoc -> Role -- See Note [unifyWanted and unifyDerived] -- The returned coercion's role matches the input parameter unifyWanted loc Phantom ty1 ty2 - = do { kind_co <- unifyWanted loc Nominal (tcTypeKind ty1) (tcTypeKind ty2) + = do { k1 <- tcTypeKindM ty1 + ; k2 <- tcTypeKindM ty2 + ; kind_co <- unifyWanted loc Nominal k1 k2 ; return (mkPhantomCo kind_co ty1 ty2) } unifyWanted loc role orig_ty1 orig_ty2 @@ -2401,9 +2401,10 @@ unifyWanted loc role orig_ty1 orig_ty2 go ty1 ty2 = bale_out ty1 ty2 bale_out ty1 ty2 - | ty1 `tcEqType` ty2 = return (mkTcReflCo role ty1) - -- Check for equality; e.g. a ~ a, or (m a) ~ (m a) - | otherwise = emitNewWantedEq loc role orig_ty1 orig_ty2 + = do { -- Check for equality; e.g. a ~ a, or (m a) ~ (m a) + already_eq <- ty1 `tcEqTypeM` ty2 + ; if already_eq then return (mkTcReflCo role ty1) + else emitNewWantedEq loc role orig_ty1 orig_ty2 } unifyDeriveds :: CtLoc -> [Role] -> [TcType] -> [TcType] -> TcS () -- See Note [unifyWanted and unifyDerived] @@ -2444,9 +2445,10 @@ unify_derived loc role orig_ty1 orig_ty2 go ty1 ty2 = bale_out ty1 ty2 bale_out ty1 ty2 - | ty1 `tcEqType` ty2 = return () - -- Check for equality; e.g. a ~ a, or (m a) ~ (m a) - | otherwise = emitNewDerivedEq loc role orig_ty1 orig_ty2 + = do { -- Check for equality; e.g. a ~ a, or (m a) ~ (m a) + already_eq <- ty1 `tcEqTypeM` ty2 + ; if already_eq then return () + else emitNewDerivedEq loc role orig_ty1 orig_ty2 } maybeSym :: SwapFlag -> TcCoercion -> TcCoercion maybeSym IsSwapped co = mkTcSymCo co diff --git a/compiler/typecheck/TcDeriv.hs b/compiler/typecheck/TcDeriv.hs index 4bbb42d4b3..fde558100b 100644 --- a/compiler/typecheck/TcDeriv.hs +++ b/compiler/typecheck/TcDeriv.hs @@ -27,6 +27,7 @@ import TcClassDcl( instDeclCtxt3, tcATDefault, tcMkDeclCtxt ) import TcEnv import TcGenDeriv -- Deriv stuff import TcValidity( checkValidInstHead ) +import TcMType( tcTypeKindM ) import InstEnv import Inst import FamInstEnv @@ -629,9 +630,9 @@ deriveStandalone (L loc (DerivDecl _ deriv_ty mbl_deriv_strat overlap_mode)) -- Perform an additional unification with the kind of the `via` -- type and the result of the previous kind unification. Just (ViaStrategy via_ty) -> do - let via_kind = tcTypeKind via_ty - inst_ty_kind = tcTypeKind inst_ty' - mb_match = tcUnifyTy inst_ty_kind via_kind + via_kind <- tcTypeKindM via_ty + inst_ty_kind <- tcTypeKindM inst_ty' + let mb_match = tcUnifyTy inst_ty_kind via_kind checkTc (isJust mb_match) (derivingViaKindErr cls inst_ty_kind @@ -788,13 +789,14 @@ deriveTyData tvs tc tc_args mb_deriv_strat deriv_pred -- See Note [tc_args and tycon arity] (tc_args_to_keep, args_to_drop) = splitAt n_args_to_keep tc_args - inst_ty_kind = tcTypeKind (mkTyConApp tc tc_args_to_keep) + enough_args = n_args_to_keep >= 0 + + ; inst_ty_kind <- tcTypeKindM (mkTyConApp tc tc_args_to_keep) - -- Match up the kinds, and apply the resulting kind substitution + ; let -- Match up the kinds, and apply the resulting kind substitution -- to the types. See Note [Unify kinds in deriving] -- We are assuming the tycon tyvars and the class tyvars are distinct - mb_match = tcUnifyTy inst_ty_kind cls_arg_kind - enough_args = n_args_to_keep >= 0 + mb_match = tcUnifyTy inst_ty_kind cls_arg_kind -- Check that the result really is well-kinded ; checkTc (enough_args && isJust mb_match) @@ -826,24 +828,21 @@ deriveTyData tvs tc tc_args mb_deriv_strat deriv_pred case mb_deriv_strat' of -- Perform an additional unification with the kind of the `via` -- type and the result of the previous kind unification. - Just (ViaStrategy via_ty) -> do - let final_via_ty = via_ty - final_via_kind = tcTypeKind final_via_ty - final_inst_ty_kind - = tcTypeKind (mkTyConApp tc final_tc_args') - via_match = tcUnifyTy final_inst_ty_kind final_via_kind - - checkTc (isJust via_match) - (derivingViaKindErr cls final_inst_ty_kind - final_via_ty final_via_kind) - - let Just via_subst = via_match - (final_tkvs, final_cls_tys, final_tc_args) - = propagate_subst via_subst tkvs' - final_cls_tys' final_tc_args' - pure ( final_tkvs, final_cls_tys, final_tc_args - , Just $ ViaStrategy $ substTy via_subst via_ty - ) + Just (ViaStrategy via_ty) -> + do { final_via_kind <- tcTypeKindM via_ty + ; final_inst_ty_kind <- tcTypeKindM (mkTyConApp tc final_tc_args') + ; let via_match = tcUnifyTy final_inst_ty_kind final_via_kind + + ; checkTc (isJust via_match) $ + derivingViaKindErr cls final_inst_ty_kind + via_ty final_via_kind + + ; let Just via_subst = via_match + (final_tkvs, final_cls_tys, final_tc_args) + = propagate_subst via_subst tkvs' + final_cls_tys' final_tc_args' + ; pure ( final_tkvs, final_cls_tys, final_tc_args + , Just $ ViaStrategy $ substTy via_subst via_ty ) } _ -> pure ( tkvs', final_cls_tys', final_tc_args' , mb_deriv_strat' ) diff --git a/compiler/typecheck/TcDerivInfer.hs b/compiler/typecheck/TcDerivInfer.hs index ba45e09dc5..df1a3a51fc 100644 --- a/compiler/typecheck/TcDerivInfer.hs +++ b/compiler/typecheck/TcDerivInfer.hs @@ -111,6 +111,8 @@ inferConstraintsDataConArgs inst_ty inst_tys , denv_cls_tys = cls_tys } <- ask wildcard <- isStandaloneWildcardDeriv + inst_ty_kind <- lift $ tcTypeKindM inst_ty + let tc_binders = tyConBinders rep_tc choose_level bndr | isNamedTyConBinder bndr = KindLevel @@ -157,7 +159,7 @@ inferConstraintsDataConArgs inst_ty inst_tys is_generic = main_cls `hasKey` genClassKey is_generic1 = main_cls `hasKey` gen1ClassKey -- is_functor_like: see Note [Inferring the instance context] - is_functor_like = tcTypeKind inst_ty `tcEqKind` typeToTypeKind + is_functor_like = inst_ty_kind `tcEqKind` typeToTypeKind || is_generic1 get_gen1_constraints :: Class -> CtOrigin -> TypeOrKind -> Type @@ -192,6 +194,8 @@ inferConstraintsDataConArgs inst_ty inst_tys -- See Note [Inferring the instance context] mk_functor_like_constraints orig t_or_k cls = map $ \ty -> let ki = tcTypeKind ty in + -- OK to use typeKind because 'ty' is a fully + -- zonked constructor argument type ( [ mk_cls_pred orig t_or_k cls ty , mkPredOrigin orig KindLevel (mkPrimEqPred ki typeToTypeKind) ] @@ -228,15 +232,17 @@ inferConstraintsDataConArgs inst_ty inst_tys -- Reason: when the IF holds, we generate a method -- dataCast2 f = gcast2 f -- and we need the Data constraints to typecheck the method - extra_constraints = [mkThetaOriginFromPreds constrs] + mk_extra_constraints + | main_cls `hasKey` dataClassKey + = do { rep_tc_arg_kinds <- lift $ mapM tcTypeKindM rep_tc_args + ; if all isLiftedTypeKind rep_tc_arg_kinds + then return [mkThetaOriginFromPreds constrs] + else return [] } + | otherwise + = return [] where - constrs - | main_cls `hasKey` dataClassKey - , all (isLiftedTypeKind . tcTypeKind) rep_tc_args - = [ mk_cls_pred deriv_origin t_or_k main_cls ty - | (t_or_k, ty) <- zip t_or_ks rep_tc_args] - | otherwise - = [] + constrs = [ mk_cls_pred deriv_origin t_or_k main_cls ty + | (t_or_k, ty) <- zip t_or_ks rep_tc_args ] mk_cls_pred orig t_or_k cls ty -- Don't forget to apply to cls_tys' too @@ -276,6 +282,7 @@ inferConstraintsDataConArgs inst_ty inst_tys [ ppr main_cls <+> ppr inst_tys' , ppr arg_constraints ] + ; extra_constraints <- mk_extra_constraints ; return ( stupid_constraints ++ extra_constraints ++ arg_constraints , tvs', inst_tys') } diff --git a/compiler/typecheck/TcErrors.hs b/compiler/typecheck/TcErrors.hs index df307f240c..0c283382c1 100644 --- a/compiler/typecheck/TcErrors.hs +++ b/compiler/typecheck/TcErrors.hs @@ -603,7 +603,7 @@ reportWanteds ctxt tc_lvl (WC { wc_simple = simples, wc_impl = implics }) is_user_type_error ct _ = isUserTypeErrorCt ct - is_homo_equality _ (EqPred _ ty1 ty2) = tcTypeKind ty1 `tcEqType` tcTypeKind ty2 + is_homo_equality _ (EqPred _ ty1 ty2) = typeKind ty1 `tcEqType` typeKind ty2 is_homo_equality _ _ = False is_equality _ (EqPred {}) = True @@ -1177,7 +1177,7 @@ mkHoleError tidy_simples ctxt ct@(CHoleCan { cc_hole = hole }) where occ = holeOcc hole hole_ty = ctEvPred (ctEvidence ct) - hole_kind = tcTypeKind hole_ty + hole_kind = typeKind hole_ty tyvars = tyCoVarsOfTypeList hole_ty hole_msg = case hole of @@ -1500,9 +1500,9 @@ mkEqErr1 ctxt ct -- Wanted or derived; || not (cty1 `pickyEqType` cty2) -> hang (text "When matching" <+> sub_what) 2 (vcat [ ppr cty1 <+> dcolon <+> - ppr (tcTypeKind cty1) + ppr (typeKind cty1) , ppr cty2 <+> dcolon <+> - ppr (tcTypeKind cty2) ]) + ppr (typeKind cty2) ]) _ -> text "When matching the kind of" <+> quotes (ppr cty1) msg2 = case sub_o of TypeEqOrigin {} @@ -1750,7 +1750,7 @@ mkTyVarEqErr' dflags ctxt report ct oriented tv1 co1 ty2 -- Not an occurs check, because F is a type function. where Pair _ k1 = tcCoercionKind co1 - k2 = tcTypeKind ty2 + k2 = typeKind ty2 ty1 = mkTyVarTy tv1 occ_check_expand = occCheckForErrors dflags tv1 ty2 @@ -1976,16 +1976,15 @@ misMatchMsg ct oriented ty1 ty2 pprWithExplicitKindsWhenMismatch :: Type -> Type -> CtOrigin -> SDoc -> SDoc pprWithExplicitKindsWhenMismatch ty1 ty2 ct = - pprWithExplicitKindsWhen mismatch + pprWithExplicitKindsWhen show_kinds where (act_ty, exp_ty) = case ct of TypeEqOrigin { uo_actual = act , uo_expected = exp } -> (act, exp) _ -> (ty1, ty2) - mismatch | Just vis <- tcEqTypeVis act_ty exp_ty - = not vis - | otherwise - = False + show_kinds = tcEqTypeVis act_ty exp_ty + -- True when the visible bit of the types look the same, + -- so we want to show the kinds in the displayed type mkExpectedActualMsg :: Type -> Type -> CtOrigin -> Maybe TypeOrKind -> Bool -> (Bool, Maybe SwapFlag, SDoc) @@ -2517,7 +2516,7 @@ mk_dict_err ctxt@(CEC {cec_encl = implics}) (ct, (matches, unifiers, unsafe_over , not (isTypeFamilyTyCon tc) = hang (text "GHC can't yet do polykinded") 2 (text "Typeable" <+> - parens (ppr ty <+> dcolon <+> ppr (tcTypeKind ty))) + parens (ppr ty <+> dcolon <+> ppr (typeKind ty))) | otherwise = empty diff --git a/compiler/typecheck/TcExpr.hs b/compiler/typecheck/TcExpr.hs index 8afcc8b666..35412f5bdb 100644 --- a/compiler/typecheck/TcExpr.hs +++ b/compiler/typecheck/TcExpr.hs @@ -387,8 +387,9 @@ tcExpr expr@(OpApp fix arg1 op arg2) res_ty -- -- The *result* type can have any kind (Trac #8739), -- so we don't need to check anything for that + ; arg2_kind <- tcTypeKindM arg2_sigma ; _ <- unifyKind (Just (XHsType $ NHsCoreTy arg2_sigma)) - (tcTypeKind arg2_sigma) liftedTypeKind + arg2_kind liftedTypeKind -- ignore the evidence. arg2_sigma must have type * or #, -- because we know arg2_sigma -> or_res_ty is well-kinded -- (because otherwise matchActualFunTys would fail) @@ -1345,9 +1346,10 @@ tcArgs fun orig_fun_ty fun_orig orig_args herald insted_ty = substTyWithInScope in_scope [tv] [ty_arg] inner_ty -- NB: tv and ty_arg have the same kind, so this -- substitution is kind-respecting + ; arg_kind <- tcTypeKindM ty_arg ; traceTc "VTA" (vcat [ppr tv, debugPprType kind - , debugPprType ty_arg - , debugPprType (tcTypeKind ty_arg) + , debugPprType ty_arg <+> dcolon + <+> debugPprType arg_kind , debugPprType inner_ty , debugPprType insted_ty ]) diff --git a/compiler/typecheck/TcFlatten.hs b/compiler/typecheck/TcFlatten.hs index b3c41a5711..a1de5a8779 100644 --- a/compiler/typecheck/TcFlatten.hs +++ b/compiler/typecheck/TcFlatten.hs @@ -1470,12 +1470,13 @@ flatten_app_ty_args fun_xi fun_co [] -- this will be a common case when called from flatten_fam_app, so shortcut = return (fun_xi, fun_co) flatten_app_ty_args fun_xi fun_co arg_tys - = do { (xi, co, kind_co) <- case tcSplitTyConApp_maybe fun_xi of + = do { let fun_kind = tcTypeKind fun_xi -- fun_xi is flat, to tcTypeKind is fine + ; (xi, co, kind_co) <- case tcSplitTyConApp_maybe fun_xi of Just (tc, xis) -> do { let tc_roles = tyConRolesRepresentational tc arg_roles = dropList xis tc_roles ; (arg_xis, arg_cos, kind_co) - <- flatten_vector (tcTypeKind fun_xi) arg_roles arg_tys + <- flatten_vector fun_kind arg_roles arg_tys -- Here, we have fun_co :: T xi1 xi2 ~ ty -- and we need to apply fun_co to the arg_cos. The problem is @@ -1494,7 +1495,7 @@ flatten_app_ty_args fun_xi fun_co arg_tys ; return (app_xi, app_co, kind_co) } Nothing -> do { (arg_xis, arg_cos, kind_co) - <- flatten_vector (tcTypeKind fun_xi) (repeat Nominal) arg_tys + <- flatten_vector fun_kind (repeat Nominal) arg_tys ; let arg_xi = mkAppTys fun_xi arg_xis arg_co = mkAppCos fun_co arg_cos ; return (arg_xi, arg_co, kind_co) } @@ -1626,8 +1627,7 @@ flatten_exact_fam_app_fully tc tys -- See Note [Reduce type family applications eagerly] -- the following tcTypeKind should never be evaluated, as it's just used in -- casting, and casts by refl are dropped - = do { let reduce_co = mkNomReflCo (tcTypeKind (mkTyConApp tc tys)) - ; mOut <- try_to_reduce_nocache tc tys reduce_co id + = do { mOut <- try_to_reduce_nocache tc tys ; case mOut of Just out -> pure out Nothing -> do @@ -1749,16 +1749,8 @@ flatten_exact_fam_app_fully tc tys try_to_reduce_nocache :: TyCon -- F, family tycon -> [Type] -- args, not necessarily flattened - -> CoercionN -- kind_co :: tcTypeKind(F args) - -- ~N tcTypeKind(F orig_args) - -- where - -- orig_args is what was passed to the - -- outer function - -> ( Coercion -- :: (xi |> kind_co) ~ F args - -> Coercion ) -- what to return from outer - -- function -> FlatM (Maybe (Xi, Coercion)) - try_to_reduce_nocache tc tys kind_co update_co + try_to_reduce_nocache tc tys = do { checkStackDepth (mkTyConApp tc tys) ; mb_match <- liftTcS $ matchFam tc tys ; case mb_match of @@ -1769,11 +1761,8 @@ flatten_exact_fam_app_fully tc tys ; eq_rel <- getEqRel ; let co = maybeSubCo eq_rel norm_co `mkTransCo` mkSymCo final_co - role = eqRelRole eq_rel - xi' = xi `mkCastTy` kind_co - co' = update_co $ - mkTcCoherenceLeftCo role xi kind_co (mkSymCo co) - ; return $ Just (xi', co') } + co' = mkSymCo co + ; return $ Just (xi, co') } Nothing -> pure Nothing } {- Note [Reduce type family applications eagerly] @@ -2062,6 +2051,7 @@ unflattenWanteds tv_eqs funeqs -- Note [Unflattening can force the solver to iterate] = ASSERT2( tyVarKind tv `eqType` tcTypeKind rhs, ppr ct ) -- CTyEqCan invariant should ensure this is true + -- We can do tcTypeKind because the constraint is inert do { is_filled <- isFilledMetaTyVar tv ; elim <- case is_filled of False -> do { traceTcS "unflatten_eq 2" (ppr ct) @@ -2102,10 +2092,9 @@ unflattenWanteds tv_eqs funeqs finalise_eq (CTyEqCan { cc_ev = ev, cc_tyvar = tv , cc_rhs = rhs, cc_eq_rel = eq_rel }) rest | isFmvTyVar tv - = do { ty1 <- zonkTcTyVar tv - ; rhs' <- zonkTcType rhs - ; if ty1 `tcEqType` rhs' - then do { setReflEvidence ev eq_rel rhs' + = do { already_eq <- mkTyVarTy tv `tcEqTypeM` rhs + ; if already_eq + then do { setReflEvidence ev eq_rel rhs ; return rest } else return (mkNonCanonical ev `consCts` rest) } diff --git a/compiler/typecheck/TcHsSyn.hs b/compiler/typecheck/TcHsSyn.hs index 6834af9f41..ec434ad415 100644 --- a/compiler/typecheck/TcHsSyn.hs +++ b/compiler/typecheck/TcHsSyn.hs @@ -1039,10 +1039,12 @@ zonk_cmd_top env (HsCmdTop (CmdTopTc stack_tys ty ids) cmd) new_ty <- zonkTcTypeToTypeX env ty new_ids <- mapSndM (zonkExpr env) ids - MASSERT( isLiftedTypeKind (tcTypeKind new_stack_tys) ) - -- desugarer assumes that this is not levity polymorphic... - -- but indeed it should always be lifted due to the typing - -- rules for arrows + when debugIsOn $ + do { new_stack_kind <- tcTypeKindM new_stack_tys + ; MASSERT( isLiftedTypeKind new_stack_kind) } + -- desugarer assumes that this is not levity polymorphic... + -- but indeed it should always be lifted due to the typing + -- rules for arrows return (HsCmdTop (CmdTopTc new_stack_tys new_ty new_ids) new_cmd) zonk_cmd_top _ (XCmdTop {}) = panic "zonk_cmd_top" diff --git a/compiler/typecheck/TcHsType.hs b/compiler/typecheck/TcHsType.hs index 182facc3fd..ca93199819 100644 --- a/compiler/typecheck/TcHsType.hs +++ b/compiler/typecheck/TcHsType.hs @@ -249,7 +249,7 @@ tc_hs_sig_type skol_info hs_sig_type ctxt_kind ; return (mkInvForAllTys kvs ty1) } -tc_hs_sig_type _ (XHsImplicitBndrs _) _ = panic "tc_hs_sig_type_and_gen" +tc_hs_sig_type _ (XHsImplicitBndrs _) _ = panic "tc_hs_sig_type" tcTopLHsType :: LHsSigType GhcRn -> ContextKind -> TcM Type -- tcTopLHsType is used for kind-checking top-level HsType where @@ -812,14 +812,10 @@ tc_hs_tuple_type mode rn_ty HsBoxedOrConstraintTuple hs_tys exp_kind -- (Either Int, Int), we do not want to get an error saying -- "the second argument of a tuple should have kind *->*" - ; tys <- zonkTcTypes tys -- Expose as much kind information as poss - - ; traceTc "tc_hs_tuple 3" $ - vcat [ ppr ty <+> dcolon <+> ppr (tcTypeKind ty) | ty <- tys ] + ; kinds <- mapM tcTypeKindM tys -- Expose as much kind information as poss ; let (arg_kind, tup_sort) - = case [ (k,s) | ty <- tys - , let k = typeKind ty + = case [ (k,s) | k <- kinds , Just s <- [tupKindSort_maybe k] ] of ((k,s) : _) -> (k,s) [] -> (liftedTypeKind, BoxedTuple) @@ -898,22 +894,15 @@ tcInferApps :: TcTyMode -> TcType -- ^ Function -> [LHsType GhcRn] -- ^ Args -> TcM TcType -- ^ (f args, args, result kind) --- Precondition: tcTypeKind fun_ty = fun_ki --- Reason: we will return a type application like (fun_ty arg1 ... argn), --- and that type must be well-kinded --- See Note [The tcType invariant] --- Postcondition: Result kind is zonked. -tcInferApps mode orig_hs_ty orig_fun_ty orig_hs_args - = do { fun_ty <- zonkTcType orig_fun_ty - ; let fun_ki = tcTypeKind fun_ty - empty_subst = mkEmptyTCvSubst $ mkInScopeSet $ +tcInferApps mode orig_hs_ty fun_ty orig_hs_args + = do { fun_ki <- tcTypeKindM fun_ty + ; let empty_subst = mkEmptyTCvSubst $ mkInScopeSet $ tyCoVarsOfType fun_ki (orig_ki_binders, orig_inner_ki) = tcSplitPiTys fun_ki ; traceTc "tcInferApps {" $ vcat [ text "orig_hs_ty:" <+> ppr orig_hs_ty , text "orig_hs_args:" <+> ppr orig_hs_args - , text "caller_fun_ty:" <+> ppr orig_fun_ty , text "fun_ty:" <+> ppr fun_ty , text "fun_ki:" <+> ppr fun_ki ] ; (f_args, _res_k) <- go 1 empty_subst fun_ty orig_ki_binders orig_inner_ki orig_hs_args @@ -1021,8 +1010,8 @@ checkExpectedKindX pp_hs_ty ty exp_kind -- foralls out front. If the actual kind has more, instantiate accordingly. -- Otherwise, just pass the type & kind through: the errors are caught -- in unifyType. - let act_kind = tcTypeKind ty - n_exp_invis_bndrs = invisibleTyBndrCount exp_kind + act_kind <- tcTypeKindM ty + ; let n_exp_invis_bndrs = invisibleTyBndrCount exp_kind n_act_invis_bndrs = invisibleTyBndrCount act_kind n_to_inst = n_act_invis_bndrs - n_exp_invis_bndrs ; (new_args, act_kind') <- tcInstTyBinders (splitPiTysInvisibleN n_to_inst act_kind) @@ -1037,8 +1026,8 @@ checkExpectedKindX pp_hs_ty ty exp_kind , text "act_kind':" <+> ppr act_kind' , text "exp_kind:" <+> ppr exp_kind ] - ; if act_kind' `tcEqType` exp_kind - then return ty' -- This is very common + ; eq_kinds <- act_kind' `tcEqTypeM` exp_kind + ; if eq_kinds then return ty' -- This is very common else do { let origin = TypeEqOrigin { uo_actual = act_kind' , uo_expected = exp_kind diff --git a/compiler/typecheck/TcInstDcls.hs b/compiler/typecheck/TcInstDcls.hs index 3b82d59b60..7f655724e9 100644 --- a/compiler/typecheck/TcInstDcls.hs +++ b/compiler/typecheck/TcInstDcls.hs @@ -793,7 +793,7 @@ tcDataFamHeader mb_clsinfo fam_tc imp_vars mb_bndrs fixity hs_ctxt hs_pats m_ksi bindImplicitTKBndrs_Q_Skol imp_vars $ bindExplicitTKBndrs_Q_Skol AnyKind exp_bndrs $ do { stupid_theta <- tcHsContext hs_ctxt - ; (lhs_ty, _) <- tcFamTyPats fam_tc mb_clsinfo hs_pats + ; lhs_ty <- tcFamTyPats fam_tc mb_clsinfo hs_pats ; mapM_ (wrapLocM_ kcConDecl) hs_cons ; res_kind <- tc_kind_sig m_ksig ; lhs_ty <- checkExpectedKindX pp_lhs lhs_ty res_kind diff --git a/compiler/typecheck/TcInteract.hs b/compiler/typecheck/TcInteract.hs index 277e3249d4..527ca31833 100644 --- a/compiler/typecheck/TcInteract.hs +++ b/compiler/typecheck/TcInteract.hs @@ -1205,6 +1205,7 @@ interactGivenIP inerts workItem@(CDictCan { cc_ev = ev, cc_class = cls filtered_dicts = addDictsByClass dicts cls other_ip_dicts -- Pick out any Given constraints for the same implicit parameter + -- Everything is inert (zonked) to ok to use tcEqType is_this_ip (CDictCan { cc_ev = ev, cc_tyargs = ip_str':_ }) = isGiven ev && ip_str `tcEqType` ip_str' is_this_ip _ = False @@ -1631,11 +1632,12 @@ solveByUnification :: CtEvidence -> TcTyVar -> Xi -> TcS () -- we often write tv := xi solveByUnification wd tv xi = do { let tv_ty = mkTyVarTy tv + ; xi_kind <- tcTypeKindM xi ; traceTcS "Sneaky unification:" $ vcat [text "Unifies:" <+> ppr tv <+> text ":=" <+> ppr xi, text "Coercion:" <+> pprEq tv_ty xi, - text "Left Kind is:" <+> ppr (tcTypeKind tv_ty), - text "Right Kind is:" <+> ppr (tcTypeKind xi) ] + text "Left Kind is:" <+> ppr (tyVarKind tv), + text "Right Kind is:" <+> ppr xi_kind ] ; unifyTyVar tv xi ; setEvBindIfWanted wd (evCoercion (mkTcNomReflCo xi)) } diff --git a/compiler/typecheck/TcMType.hs b/compiler/typecheck/TcMType.hs index 0ca27f57d0..1486d656f4 100644 --- a/compiler/typecheck/TcMType.hs +++ b/compiler/typecheck/TcMType.hs @@ -37,6 +37,10 @@ module TcMType ( tauifyExpType, inferResultToType, -------------------------------- + -- Getting the kind of a type + tcEqTypeM, tcTypeKindM, piResultTysM, + + -------------------------------- -- Creating new evidence variables newEvVar, newEvVars, newDict, newWanted, newWanteds, newHoleCt, cloneWanted, cloneWC, @@ -60,18 +64,21 @@ module TcMType ( freshenTyVarBndrs, freshenCoVarBndrsX, -------------------------------- + -- Quantification + candidateQTyVarsOfType, candidateQTyVarsOfKind, + candidateQTyVarsOfTypes, candidateQTyVarsOfKinds, + CandidatesQTvs(..), delCandidates, candidateKindVars, + skolemiseQuantifiedTyVar, defaultTyVar, + quantifyTyVars, + + -------------------------------- -- Zonking and tidying zonkTidyTcType, zonkTidyTcTypes, zonkTidyOrigin, tidyEvVar, tidyCt, tidySkolemInfo, - zonkTcTyVar, zonkTcTyVars, + zonkTcTyVar, zonkTcTyVars, zonkTcTyVarToTyVar, zonkTyVarTyVarPairs, zonkTyCoVarsAndFV, zonkTcTypeAndFV, zonkTyCoVarsAndFVList, - candidateQTyVarsOfType, candidateQTyVarsOfKind, - candidateQTyVarsOfTypes, candidateQTyVarsOfKinds, - CandidatesQTvs(..), delCandidates, candidateKindVars, - skolemiseQuantifiedTyVar, defaultTyVar, - quantifyTyVars, zonkTcTyCoVarBndr, zonkTyConBinders, zonkTcType, zonkTcTypes, zonkCo, zonkTyCoVarKind, @@ -128,6 +135,221 @@ import qualified Data.Semigroup as Semi {- ************************************************************************ * * + tcTypeKind +* * +************************************************************************ +-} + +tcTypeKindM :: HasDebugCallStack => TcType -> TcM TcKind +tcTypeKindM (TyConApp tc tys) = return (piResultTys (tyConKind tc) tys) +tcTypeKindM (LitTy l) = return (typeLiteralKind l) +tcTypeKindM (CastTy _ty co) = return (pSnd $ coercionKind co) +tcTypeKindM (CoercionTy co) = return (coercionType co) + +tcTypeKindM (FunTy arg res) + = do { arg_k <- tcTypeKindM arg + ; if tcIsConstraintKind arg_k + then do { res_k <- tcTypeKindM res + ; if tcIsConstraintKind res_k + then return constraintKind + else return liftedTypeKind } + else return liftedTypeKind } + +tcTypeKindM (AppTy fun arg) + = go fun [arg] + where + -- Accumulate the type arugments, so we can call piResultTys, + -- rather than a succession of calls to piResultTy (which is + -- asymptotically costly as the number of arguments increases) + go (AppTy fun arg) args = go fun (arg:args) + go fun args = do { fun_k <- tcTypeKindM fun + ; piResultTysM fun_k args } + +tcTypeKindM ty@(ForAllTy {}) + = do { body_k <- tcTypeKindM body + ; if tcIsConstraintKind body_k + then return constraintKind + else case occCheckExpand tvs body_k of -- We must make sure tv does + Just k' -> return k' -- not occur in kind + Nothing -> pprPanic "tcTypeKindM" + (ppr ty $$ ppr tvs $$ ppr body <+> dcolon <+> ppr body_k) } + where + (tvs, body) = splitTyVarForAllTys ty + +tcTypeKindM (TyVarTy tv) + | isMetaTyVar tv + = do { maybe_ty <- readMetaTyVar tv + ; case maybe_ty of + Indirect ty -> tcTypeKindM ty + Flexi -> return (tyVarKind tv) } + | otherwise + = return (tyVarKind tv) + +piResultTysM :: HasDebugCallStack => TcType -> [TcType] -> TcM TcType +piResultTysM ty orig_args = go init_subst ty orig_args + where + init_subst = mkEmptyTCvSubst $ mkInScopeSet (tyCoVarsOfTypes (ty:orig_args)) + + go :: TCvSubst -> TcType -> [TcType] -> TcM TcType + go subst ty [] + = return (substTy subst ty) -- substTy has a fast-path for empty substitutions + + go subst ty all_args@(arg:args) + | Just ty' <- tcView ty + = go subst ty' all_args + + | FunTy _ res <- ty + = go subst res args + + | ForAllTy (Bndr tv _) res <- ty + = go (extendTCvSubst subst tv arg) res args + + | TyVarTy tv <- ty + , isMetaTyVar tv + = do { maybe_ty <- readMetaTyVar tv + ; case maybe_ty of + Indirect ty -> go subst ty all_args + Flexi -> try_subst subst ty all_args } + + | otherwise + = try_subst subst ty all_args + + try_subst subst ty args + | not (isEmptyTCvSubst subst) -- See Note [Care with kind instantiation] + = go init_subst (substTy subst ty) args + + | otherwise + = -- We have not run out of arguments, but the function doesn't + -- have the right kind to apply to them; so panic. + -- Without the explicit isEmptyVarEnv test, an ill-kinded type + -- would give an infniite loop, which is very unhelpful + -- c.f. Trac #15473 + pprPanic "piResultTysM" (ppr ty $$ ppr orig_args $$ ppr args) + + +-- | A monadic version of tcEqType +-- If it returns True, the two types are definitely equal +-- If not, they might still be equal, after zonking +-- Reason for this one-sided conservative-ness: tcEqTypeM is used only +-- for fast-path checks, and we don't want the full glory of RnEnv2, +-- which requires us to find the free vars to find the in-scope set, +-- which requires zonking... and is almost never necessary +tcEqTypeM :: TcType -> TcType -> TcM Bool +tcEqTypeM t1 t2 + = do { k1 <- tcTypeKindM t1 + ; k2 <- tcTypeKindM t2 + ; tc_eq_type_m k1 k2 `scAndM` tc_eq_type_m t1 t2 } + +tc_eq_type_m :: TcType -> TcType -> TcM Bool +tc_eq_type_m orig_ty1 orig_ty2 + = go orig_ty1 orig_ty2 + where + go :: TcType -> TcType -> TcM Bool + go t1 t2 | Just t1' <- tcView t1 = go t1' t2 + go t1 t2 | Just t2' <- tcView t2 = go t1 t2' + + go (TyVarTy tv1) t2 = go_tv tv1 t2 + go t1 (TyVarTy tv2) = go_tv tv2 t1 + + go (LitTy lit1) (LitTy lit2) + = return (lit1 == lit2) + + go t1@(ForAllTy {}) t2 = return (tcEqTypeNoKindCheck t1 t2) + go t1 t2@(ForAllTy {}) = return (tcEqTypeNoKindCheck t1 t2) + + -- 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 (FunTy arg1 res1) (FunTy arg2 res2) + = go arg1 arg2 `scAndM` go res1 res2 + go ty (FunTy arg res) = eqFunTy arg res ty + go (FunTy arg res) ty = eqFunTy arg res ty + + -- See Note [Equality on AppTys] in Type + go (AppTy s1 t1) ty2 + | Just (s2, t2) <- repSplitAppTy_maybe ty2 + = go s1 s2 `scAndM` go t1 t2 + go ty1 (AppTy s2 t2) + | Just (s1, t1) <- repSplitAppTy_maybe ty1 + = go s1 s2 `scAndM` go t1 t2 + + go (TyConApp tc1 ts1) (TyConApp tc2 ts2) + | tc1 == tc2 = gos ts1 ts2 + | otherwise = return False + + go (CastTy t1 _) t2 = go t1 t2 + go t1 (CastTy t2 _) = go t1 t2 + go (CoercionTy {}) (CoercionTy {}) = return True + + go _ _ = return False + + -------- + gos [] [] = return True + gos (t1:ts1) (t2:ts2) = go t1 t2 `scAndM` gos ts1 ts2 + gos _ _ = return False + + -------- + go_tv :: TcTyVar -> TcType -> TcM Bool + go_tv tv1 t2 + | isMetaTyVar tv1 + = do { mb_t1 <- readMetaTyVar tv1 + ; case mb_t1 of + Indirect t1 -> go t1 t2 + Flexi -> go_tv1 tv1 t2 } + | otherwise + = go_tv1 tv1 t2 + + -------- + go_tv1 :: TcTyVar -> TcType -> TcM Bool + -- tv1 is not a filled-in meta-tyvar + go_tv1 tv1 (TyVarTy tv2) + | isMetaTyVar tv2 + = do { mb_t2 <- readMetaTyVar tv2 + ; case mb_t2 of + Indirect t2 -> go_tv1 tv1 t2 + Flexi -> go_tv2 tv1 tv2 } + | otherwise + = go_tv2 tv1 tv2 + + go_tv1 _ _ = return False -- TyVar vs non-TyVar + + -------- + go_tv2 :: TcTyVar -> TcTyVar -> TcM Bool + -- Neither is a filled-in meta-tyvar + go_tv2 tv1 tv2 = return (tv1 == tv2) + + -------- + -- @eqFunTy arg res ty@ is True when @ty@ equals @FunTy arg res@. This is + -- sometimes hard to know directly because @ty@ might have some casts + -- obscuring the FunTy. And 'splitAppTy' is difficult because we can't + -- 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 :: Type -> Type -> Type -> TcM Bool + -- Last arg is /not/ FunTy + eqFunTy arg res ty@(AppTy{}) = get_args ty [] + where + get_args :: Type -> [Type] -> TcM 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 + | tc == funTyCon + , [_, _, arg', res'] <- tys ++ args + = go arg arg' <&&> go res res' + get_args _ _ = return False + eqFunTy _ _ _ = return False + +scAndM :: TcM Bool -> TcM Bool -> TcM Bool +-- A short-circuiting 'and' for monadic computations +-- If the first returns False, it does not do the second at all +-- (Whereas <&&> does the seecond regardless.) +scAndM mb1 mb2 = do { b1 <- mb1 + ; if b1 then mb2 + else return False } + +{- +************************************************************************ +* * Kind variables * * ************************************************************************ @@ -684,7 +906,8 @@ newFskTyVar fam_ty , mtv_ref = ref , mtv_tclvl = tclvl } name = mkMetaTyVarName uniq (fsLit "fsk") - ; return (mkTcTyVar name (tcTypeKind fam_ty) details) } + ; fam_ty_kind <- tcTypeKindM fam_ty + ; return (mkTcTyVar name fam_ty_kind details) } newFmvTyVar :: TcType -> TcM TcTyVar -- Very like newMetaTyVar, except sets mtv_tclvl to one less @@ -697,7 +920,8 @@ newFmvTyVar fam_ty , mtv_ref = ref , mtv_tclvl = tclvl } name = mkMetaTyVarName uniq (fsLit "s") - ; return (mkTcTyVar name (tcTypeKind fam_ty) details) } + ; fam_ty_kind <- tcTypeKindM fam_ty + ; return (mkTcTyVar name fam_ty_kind details) } newMetaDetails :: MetaInfo -> TcM TcTyVarDetails newMetaDetails info @@ -784,10 +1008,9 @@ writeMetaTyVarRef tyvar ref ty = do { meta_details <- readMutVar ref; -- Zonk kinds to allow the error check to work ; zonked_tv_kind <- zonkTcType tv_kind - ; zonked_ty <- zonkTcType ty - ; let zonked_ty_kind = tcTypeKind zonked_ty -- Need to zonk even before typeKind; - -- otherwise, we can panic in piResultTy - kind_check_ok = tcIsConstraintKind zonked_tv_kind + ; ty_kind <- tcTypeKindM ty + ; zonked_ty_kind <- zonkTcType ty_kind + ; let kind_check_ok = tcIsConstraintKind zonked_tv_kind || tcEqKind zonked_ty_kind zonked_tv_kind -- Hack alert! tcIsConstraintKind: see TcHsType -- Note [Extra-constraint holes in partial type signatures] @@ -2199,4 +2422,4 @@ formatLevPolyErr ty , text "Kind:" <+> pprWithTYPE tidy_ki ]) where (tidy_env, tidy_ty) = tidyOpenType emptyTidyEnv ty - tidy_ki = tidyType tidy_env (tcTypeKind ty) + tidy_ki = tidyType tidy_env (typeKind ty) diff --git a/compiler/typecheck/TcPat.hs b/compiler/typecheck/TcPat.hs index ba3603fb42..38236afbdf 100644 --- a/compiler/typecheck/TcPat.hs +++ b/compiler/typecheck/TcPat.hs @@ -351,7 +351,8 @@ tc_pat penv (LazyPat x pat) pat_ty thing_inside -- Check that the expected pattern type is itself lifted ; pat_ty <- readExpType pat_ty - ; _ <- unifyType Nothing (tcTypeKind pat_ty) liftedTypeKind + ; pat_kind <- tcTypeKindM pat_ty + ; _ <- unifyType Nothing pat_kind liftedTypeKind ; return (LazyPat x pat', res) } diff --git a/compiler/typecheck/TcPatSyn.hs b/compiler/typecheck/TcPatSyn.hs index ea1f483268..370e62f998 100644 --- a/compiler/typecheck/TcPatSyn.hs +++ b/compiler/typecheck/TcPatSyn.hs @@ -53,7 +53,6 @@ import FieldLabel import Bag import Util import ErrUtils -import Data.Maybe( mapMaybe ) import Control.Monad ( zipWithM ) import Data.List( partition ) @@ -166,8 +165,8 @@ tcInferPatSynDecl (PSB { psb_id = lname@(dL->L _ name), psb_args = details do { prov_dicts <- mapM zonkId prov_dicts ; let filtered_prov_dicts = mkMinimalBySCs evVarPred prov_dicts -- Filtering: see Note [Remove redundant provided dicts] - (prov_theta, prov_evs) - = unzip (mapMaybe mkProvEvidence filtered_prov_dicts) + ; pairs <- mapMaybeM mkProvEvidence filtered_prov_dicts + ; let (prov_theta, prov_evs) = unzip pairs req_theta = map evVarPred req_dicts -- Report coercions that esacpe @@ -189,29 +188,30 @@ tcInferPatSynDecl (PSB { psb_id = lname@(dL->L _ name), psb_args = details pat_ty rec_fields } } tcInferPatSynDecl (XPatSynBind _) = panic "tcInferPatSynDecl" -mkProvEvidence :: EvId -> Maybe (PredType, EvTerm) +mkProvEvidence :: EvId -> TcM (Maybe (PredType, EvTerm)) -- See Note [Equality evidence in pattern synonyms] mkProvEvidence ev_id | EqPred r ty1 ty2 <- classifyPredType pred - , let k1 = tcTypeKind ty1 - k2 = tcTypeKind ty2 - is_homo = k1 `tcEqType` k2 - homo_tys = [k1, ty1, ty2] - hetero_tys = [k1, k2, ty1, ty2] - = case r of - ReprEq | is_homo - -> Just ( mkClassPred coercibleClass homo_tys - , evDataConApp coercibleDataCon homo_tys eq_con_args ) - | otherwise -> Nothing - NomEq | is_homo - -> Just ( mkClassPred eqClass homo_tys - , evDataConApp eqDataCon homo_tys eq_con_args ) - | otherwise - -> Just ( mkClassPred heqClass hetero_tys - , evDataConApp heqDataCon hetero_tys eq_con_args ) + = do { k1 <- tcTypeKindM ty1 + ; k2 <- tcTypeKindM ty2 + ; is_homo <- k1 `tcEqTypeM` k2 + ; let homo_tys = [k1, ty1, ty2] + hetero_tys = [k1, k2, ty1, ty2] + ; return $ + case r of + ReprEq | is_homo + -> Just ( mkClassPred coercibleClass homo_tys + , evDataConApp coercibleDataCon homo_tys eq_con_args ) + | otherwise -> Nothing + NomEq | is_homo + -> Just ( mkClassPred eqClass homo_tys + , evDataConApp eqDataCon homo_tys eq_con_args ) + | otherwise + -> Just ( mkClassPred heqClass hetero_tys + , evDataConApp heqDataCon hetero_tys eq_con_args ) } | otherwise - = Just (pred, EvExpr (evId ev_id)) + = return (Just (pred, EvExpr (evId ev_id))) where pred = evVarPred ev_id eq_con_args = [evId ev_id] diff --git a/compiler/typecheck/TcRnDriver.hs b/compiler/typecheck/TcRnDriver.hs index 5e6f6308e0..8ed21f2d81 100644 --- a/compiler/typecheck/TcRnDriver.hs +++ b/compiler/typecheck/TcRnDriver.hs @@ -2400,7 +2400,8 @@ tcRnType hsc_env normalise rdr_type ; _ <- checkNoErrs (simplifyInteractive lie) -- Do kind generalisation; see Note [Kind-generalise in tcRnType] - ; kvs <- kindGeneralize (tcTypeKind ty) + ; kind <- tcTypeKindM ty + ; kvs <- kindGeneralize kind ; ty <- zonkTcTypeToType ty -- Do validity checking on type @@ -2408,12 +2409,12 @@ tcRnType hsc_env normalise rdr_type ; ty' <- if normalise then do { fam_envs <- tcGetFamInstEnvs - ; let (_, ty') - = normaliseType fam_envs Nominal ty + ; let (_, ty') = normaliseType fam_envs Nominal ty ; return ty' } else return ty ; - ; return (ty', mkInvForAllTys kvs (tcTypeKind ty')) } + ; kind' <- tcTypeKindM ty' + ; return (ty', mkInvForAllTys kvs kind') } {- Note [TcRnExprMode] ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/compiler/typecheck/TcSMonad.hs b/compiler/typecheck/TcSMonad.hs index 69f58b9002..587a26fd0a 100644 --- a/compiler/typecheck/TcSMonad.hs +++ b/compiler/typecheck/TcSMonad.hs @@ -105,7 +105,7 @@ module TcSMonad ( zonkTyCoVarsAndFV, zonkTcType, zonkTcTypes, zonkTcTyVar, zonkCo, zonkTyCoVarsAndFVList, zonkSimples, zonkWC, - zonkTyCoVarKind, + zonkTyCoVarKind, tcEqTypeM, tcTypeKindM, -- References newTcRef, readTcRef, writeTcRef, updTcRef, @@ -3126,6 +3126,13 @@ zonkWC wc = wrapTcS (TcM.zonkWC wc) zonkTyCoVarKind :: TcTyCoVar -> TcS TcTyCoVar zonkTyCoVarKind tv = wrapTcS (TcM.zonkTyCoVarKind tv) +tcEqTypeM :: TcType -> TcType -> TcS Bool +tcEqTypeM ty1 ty2 = wrapTcS (TcM.tcEqTypeM ty1 ty2) + +tcTypeKindM :: TcType -> TcS TcKind +tcTypeKindM ty = wrapTcS (TcM.tcTypeKindM ty) + + {- ********************************************************************* * * * Flatten skolems * @@ -3399,10 +3406,8 @@ newGivenEvVars loc pts = mapM (newGivenEvVar loc) pts emitNewWantedEq :: CtLoc -> Role -> TcType -> TcType -> TcS Coercion -- | Emit a new Wanted equality into the work-list emitNewWantedEq loc role ty1 ty2 - | otherwise = do { (ev, co) <- newWantedEq loc role ty1 ty2 - ; updWorkListTcS $ - extendWorkListEq (mkNonCanonical ev) + ; updWorkListTcS $ extendWorkListEq (mkNonCanonical ev) ; return co } -- | Make a new equality CtEvidence diff --git a/compiler/typecheck/TcSplice.hs b/compiler/typecheck/TcSplice.hs index c51771d225..08b2992809 100644 --- a/compiler/typecheck/TcSplice.hs +++ b/compiler/typecheck/TcSplice.hs @@ -1199,7 +1199,7 @@ reifyInstances th_nm th_tys -- In particular, the type might have kind -- variables inside it (Trac #7477) - ; traceTc "reifyInstances" (ppr ty $$ ppr (tcTypeKind ty)) + ; traceTc "reifyInstances" (ppr ty $$ ppr (typeKind ty)) ; case splitTyConApp_maybe ty of -- This expands any type synonyms Just (tc, tys) -- See Trac #7910 | Just cls <- tyConClass_maybe tc @@ -1639,7 +1639,7 @@ annotThType :: Bool -- True <=> annotate annotThType _ _ th_ty@(TH.SigT {}) = return th_ty annotThType True ty th_ty | not $ isEmptyVarSet $ filterVarSet isTyVar $ tyCoVarsOfType ty - = do { let ki = tcTypeKind ty + = do { ki <- tcTypeKindM ty ; th_ki <- reifyKind ki ; return (TH.SigT th_ty th_ki) } annotThType _ _ th_ty = return th_ty @@ -1944,7 +1944,7 @@ reify_tc_app tc tys -- See Note [Kind annotations on TyConApps] maybe_sig_t th_type | needs_kind_sig - = do { let full_kind = tcTypeKind (mkTyConApp tc tys) + = do { full_kind <- tcTypeKindM (mkTyConApp tc tys) ; th_full_kind <- reifyKind full_kind ; return (TH.SigT th_type th_full_kind) } | otherwise diff --git a/compiler/typecheck/TcTyClsDecls.hs b/compiler/typecheck/TcTyClsDecls.hs index 9b399281ff..8615347c50 100644 --- a/compiler/typecheck/TcTyClsDecls.hs +++ b/compiler/typecheck/TcTyClsDecls.hs @@ -1742,7 +1742,8 @@ kcTyFamInstEqn tc_fam_tc ; discardResult $ bindImplicitTKBndrs_Q_Tv imp_vars $ bindExplicitTKBndrs_Q_Tv AnyKind (mb_expl_bndrs `orElse` []) $ - do { (_, res_kind) <- tcFamTyPats tc_fam_tc NotAssociated hs_pats + do { fam_app <- tcFamTyPats tc_fam_tc NotAssociated hs_pats + ; res_kind <- tcTypeKindM fam_app ; tcCheckLHsType hs_rhs_ty res_kind } -- Why "_Tv" here? Consider (Trac #14066 -- type family Bar x y where @@ -1893,7 +1894,9 @@ tcTyFamInstEqnGuts fam_tc mb_clsinfo imp_vars exp_bndrs hs_pats hs_rhs_ty (tyConKind fam_tc) ; return (mkTyConApp fam_tc args, rhs_kind) } | otherwise - = tcFamTyPats fam_tc mb_clsinfo hs_pats + = do { fam_app <- tcFamTyPats fam_tc mb_clsinfo hs_pats + ; res_kind <- tcTypeKindM fam_app + ; return (fam_app, res_kind) } {- Note [Apparently-nullary families] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1941,7 +1944,7 @@ tcFamTyPats fam_tc mb_clsinfo hs_pats -- Ensure that the instance is consistent its parent class ; addConsistencyConstraints mb_clsinfo fam_app - ; return (fam_app, tcTypeKind fam_app) } + ; return fam_app } where fam_name = tyConName fam_tc fam_arity = tyConArity fam_tc @@ -2438,8 +2441,8 @@ rejigConRes tmpl_bndrs res_tmpl dc_inferred_tvs dc_specified_tvs res_ty -- So we return ( [a,b,z], [x,y] -- , [], [x,y,z] -- , [a~(x,y),b~z], <arg-subst> ) - | Just subst <- ASSERT( isLiftedTypeKind (tcTypeKind res_ty) ) - ASSERT( isLiftedTypeKind (tcTypeKind res_tmpl) ) + | Just subst <- ASSERT( isLiftedTypeKind (typeKind res_ty) ) + ASSERT( isLiftedTypeKind (typeKind res_tmpl) ) tcMatchTy res_tmpl res_ty = let (univ_tvs, raw_eqs, kind_subst) = mkGADTVars tmpl_tvs dc_tvs subst raw_ex_tvs = dc_tvs `minusList` univ_tvs @@ -2959,8 +2962,8 @@ checkValidDataCon dflags existential_ok tc con orig_res_ty = dataConOrigResTy con ; traceTc "checkValidDataCon" (vcat [ ppr con, ppr tc, ppr tc_tvs - , ppr res_ty_tmpl <+> dcolon <+> ppr (tcTypeKind res_ty_tmpl) - , ppr orig_res_ty <+> dcolon <+> ppr (tcTypeKind orig_res_ty)]) + , ppr res_ty_tmpl <+> dcolon <+> ppr (typeKind res_ty_tmpl) + , ppr orig_res_ty <+> dcolon <+> ppr (typeKind orig_res_ty)]) ; checkTc (isJust (tcMatchTy res_ty_tmpl 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 diff --git a/compiler/typecheck/TcUnify.hs b/compiler/typecheck/TcUnify.hs index f51c7241a8..6840a14ef5 100644 --- a/compiler/typecheck/TcUnify.hs +++ b/compiler/typecheck/TcUnify.hs @@ -435,16 +435,15 @@ matchExpectedAppTy orig_ty -- Defer splitting by generating an equality constraint defer - = do { ty1 <- newFlexiTyVarTy kind1 + = do { orig_kind <- tcTypeKindM orig_ty + ; let kind1 = mkFunTy liftedTypeKind orig_kind + kind2 = liftedTypeKind -- m :: * -> k + -- arg type :: * + ; ty1 <- newFlexiTyVarTy kind1 ; ty2 <- newFlexiTyVarTy kind2 ; co <- unifyType Nothing (mkAppTy ty1 ty2) orig_ty ; return (co, (ty1, ty2)) } - orig_kind = tcTypeKind orig_ty - kind1 = mkFunTy liftedTypeKind orig_kind - kind2 = liftedTypeKind -- m :: * -> k - -- arg type :: * - {- ************************************************************************ * * @@ -790,7 +789,7 @@ tc_sub_type_ds eq_orig inst_orig ctxt ty_actual ty_expected inst_and_unify = do { (wrap, rho_a) <- deeplyInstantiate inst_orig ty_actual - -- if we haven't recurred through an arrow, then + -- If we haven't recurred through an arrow, then -- the eq_orig will list ty_actual. In this case, -- we want to update the origin to reflect the -- instantiation. If we *have* recurred through @@ -909,9 +908,11 @@ fill_infer_result orig_ty (IR { ir_uniq = u, ir_lvl = res_lvl where check_hole ty -- Debug check only = do { let ty_lvl = tcTypeLevel ty - ; MASSERT2( not (ty_lvl `strictlyDeeperThan` res_lvl), - ppr u $$ ppr res_lvl $$ ppr ty_lvl $$ - ppr ty <+> dcolon <+> ppr (tcTypeKind ty) $$ ppr orig_ty ) + ; when debugIsOn $ + do { kind <- tcTypeKindM ty + ; MASSERT2( not (ty_lvl `strictlyDeeperThan` res_lvl) + , ppr u $$ ppr res_lvl $$ ppr ty_lvl $$ + ppr ty <+> dcolon <+> ppr kind $$ ppr orig_ty ) } ; cts <- readTcRef ref ; case cts of Just already_there -> pprPanic "writeExpType" @@ -993,12 +994,12 @@ promoteTcType dest_lvl ty dont_promote_it :: TcM (TcCoercion, TcType) dont_promote_it -- Check that ty :: TYPE rr, for some (fresh) rr = do { res_kind <- newOpenTypeKind - ; let ty_kind = tcTypeKind ty - kind_orig = TypeEqOrigin { uo_actual = ty_kind + ; ty_kind <- tcTypeKindM ty + ; let kind_orig = TypeEqOrigin { uo_actual = ty_kind , uo_expected = res_kind , uo_thing = Nothing , uo_visible = False } - ; ki_co <- uType KindLevel kind_orig (tcTypeKind ty) res_kind + ; ki_co <- uType KindLevel kind_orig ty_kind res_kind ; let co = mkTcGReflRightCo Nominal ty ki_co ; return (co, ty `mkCastTy` ki_co) } @@ -1639,10 +1640,11 @@ uUnfilledVar2 origin t_or_k swapped tv1 ty2 go dflags cur_lvl | canSolveByUnification cur_lvl tv1 ty2 , Just ty2' <- metaTyVarUpdateOK dflags tv1 ty2 - = do { co_k <- uType KindLevel kind_origin (tcTypeKind ty2') (tyVarKind tv1) + = do { k2' <- tcTypeKindM ty2' + ; co_k <- uType KindLevel kind_origin k2' (tyVarKind tv1) ; traceTc "uUnfilledVar2 ok" $ vcat [ ppr tv1 <+> dcolon <+> ppr (tyVarKind tv1) - , ppr ty2 <+> dcolon <+> ppr (tcTypeKind ty2) + , ppr ty2 <+> dcolon <+> ppr k2' , ppr (isTcReflCo co_k), ppr co_k ] ; if isTcReflCo co_k -- only proceed if the kinds matched. diff --git a/compiler/types/Type.hs b/compiler/types/Type.hs index 0fff81c2ab..2321bf4f32 100644 --- a/compiler/types/Type.hs +++ b/compiler/types/Type.hs @@ -39,7 +39,7 @@ module Type ( mkForAllTy, mkForAllTys, mkTyCoInvForAllTys, mkSpecForAllTys, mkVisForAllTys, mkTyCoInvForAllTy, mkInvForAllTy, mkInvForAllTys, - splitForAllTys, splitForAllVarBndrs, + splitForAllTys, splitTyVarForAllTys, splitForAllVarBndrs, splitForAllTy_maybe, splitForAllTy, splitForAllTy_ty_maybe, splitForAllTy_co_maybe, splitPiTy_maybe, splitPiTy, splitPiTys, @@ -132,7 +132,7 @@ module Type ( Kind, -- ** Finding the kind of a type - typeKind, tcTypeKind, isTypeLevPoly, resultIsLevPoly, + typeKind, tcTypeKind, typeLiteralKind, isTypeLevPoly, resultIsLevPoly, tcIsLiftedTypeKind, tcIsConstraintKind, tcReturnsConstraintKind, -- ** Common Kind @@ -1820,6 +1820,10 @@ isEvVarType :: Type -> Bool -- See Note [Evidence for quantified constraints] isEvVarType ty = isCoVarType ty || isPredTy ty +isPredTy :: Type -> Bool +-- See Note [Types for coercions, predicates, and evidence] +isPredTy ty = tcIsConstraintKind (typeKind ty) + -- | Does this type classify a core (unlifted) Coercion? -- At either role nominal or representational -- (t1 ~# t2) or (t1 ~R# t2) @@ -2701,6 +2705,7 @@ Note that: ----------------------------- typeKind :: HasDebugCallStack => Type -> Kind +-- No need to expand synonyms typeKind (TyConApp tc tys) = piResultTys (tyConKind tc) tys typeKind (LitTy l) = typeLiteralKind l typeKind (FunTy {}) = liftedTypeKind @@ -2726,17 +2731,17 @@ typeKind ty@(ForAllTy {}) (tvs, body) = splitTyVarForAllTys ty body_kind = typeKind body ------------------------------ +---------------------------- tcTypeKind :: HasDebugCallStack => Type -> Kind +-- No need to expand synonyms tcTypeKind (TyConApp tc tys) = piResultTys (tyConKind tc) tys tcTypeKind (LitTy l) = typeLiteralKind l -tcTypeKind (TyVarTy tyvar) = tyVarKind tyvar -tcTypeKind (CastTy _ty co) = pSnd $ coercionKind co -tcTypeKind (CoercionTy co) = coercionType co - tcTypeKind (FunTy arg res) - | isPredTy arg && isPredTy res = constraintKind - | otherwise = liftedTypeKind + | isPredTy arg, isPredTy res = constraintKind + | otherwise = liftedTypeKind +tcTypeKind (TyVarTy tyvar) = tyVarKind tyvar +tcTypeKind (CastTy _ty co) = pSnd $ coercionKind co +tcTypeKind (CoercionTy co) = coercionType co tcTypeKind (AppTy fun arg) = go fun [arg] @@ -2750,7 +2755,6 @@ tcTypeKind (AppTy fun arg) tcTypeKind ty@(ForAllTy {}) | tcIsConstraintKind body_kind = constraintKind - | otherwise = case occCheckExpand tvs body_kind of -- We must make sure tv does not occur in kind Just k' -> k' -- As it is already out of scope! @@ -2758,19 +2762,12 @@ tcTypeKind ty@(ForAllTy {}) (ppr ty $$ ppr tvs $$ ppr body <+> dcolon <+> ppr body_kind) where (tvs, body) = splitTyVarForAllTys ty - body_kind = tcTypeKind body - - -isPredTy :: Type -> Bool --- See Note [Types for coercions, predicates, and evidence] -isPredTy ty = tcIsConstraintKind (tcTypeKind ty) + body_kind = tcTypeKind body -------------------------- typeLiteralKind :: TyLit -> Kind -typeLiteralKind l = - case l of - NumTyLit _ -> typeNatKind - StrTyLit _ -> typeSymbolKind +typeLiteralKind (NumTyLit {}) = typeNatKind +typeLiteralKind (StrTyLit {}) = typeSymbolKind -- | Returns True if a type is levity polymorphic. Should be the same -- as (isKindLevPoly . typeKind) but much faster. |