diff --git a/compiler/GHC/Core/Coercion.hs b/compiler/GHC/Core/Coercion.hs index 21d537112e43a6235ae8b0f827edcce0fcabb124..9000e7a399e94578b5db79732563769f503be94c 100644 --- a/compiler/GHC/Core/Coercion.hs +++ b/compiler/GHC/Core/Coercion.hs @@ -41,7 +41,7 @@ module GHC.Core.Coercion ( mkInstCo, mkAppCo, mkAppCos, mkTyConAppCo, mkFunCo, mkFunCo2, mkFunCoNoFTF, mkFunResCo, mkNakedFunCo, - mkForAllCo, mkForAllCos, mkHomoForAllCos, + mkNakedForAllCo, mkForAllCo, mkHomoForAllCos, mkPhantomCo, mkHoleCo, mkUnivCo, mkSubCo, mkAxiomInstCo, mkProofIrrelCo, @@ -74,7 +74,7 @@ module GHC.Core.Coercion ( mkCoherenceRightMCo, coToMCo, mkTransMCo, mkTransMCoL, mkTransMCoR, mkCastTyMCo, mkSymMCo, - mkHomoForAllMCo, mkFunResMCo, mkPiMCos, + mkFunResMCo, mkPiMCos, isReflMCo, checkReflexiveMCo, -- ** Coercion variables @@ -138,7 +138,7 @@ import GHC.Core.TyCo.FVs import GHC.Core.TyCo.Ppr import GHC.Core.TyCo.Subst import GHC.Core.TyCo.Tidy -import GHC.Core.TyCo.Compare( eqType, eqTypeX ) +import GHC.Core.TyCo.Compare import GHC.Core.Type import GHC.Core.TyCon import GHC.Core.TyCon.RecWalk @@ -169,6 +169,7 @@ import Control.Monad (foldM, zipWithM) import Data.Function ( on ) import Data.Char( isDigit ) import qualified Data.Monoid as Monoid +import Control.DeepSeq {- %************************************************************************ @@ -361,10 +362,6 @@ mkCastTyMCo :: Type -> MCoercion -> Type mkCastTyMCo ty MRefl = ty mkCastTyMCo ty (MCo co) = ty `mkCastTy` co -mkHomoForAllMCo :: TyCoVar -> MCoercion -> MCoercion -mkHomoForAllMCo _ MRefl = MRefl -mkHomoForAllMCo tcv (MCo co) = MCo (mkHomoForAllCos [tcv] co) - mkPiMCos :: [Var] -> MCoercion -> MCoercion mkPiMCos _ MRefl = MRefl mkPiMCos vs (MCo co) = MCo (mkPiCos Representational vs co) @@ -555,22 +552,29 @@ splitFunCo_maybe :: Coercion -> Maybe (Coercion, Coercion) splitFunCo_maybe (FunCo { fco_arg = arg, fco_res = res }) = Just (arg, res) splitFunCo_maybe _ = Nothing -splitForAllCo_maybe :: Coercion -> Maybe (TyCoVar, Coercion, Coercion) -splitForAllCo_maybe (ForAllCo tv k_co co) = Just (tv, k_co, co) -splitForAllCo_maybe _ = Nothing +splitForAllCo_maybe :: Coercion -> Maybe (TyCoVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion) +splitForAllCo_maybe (ForAllCo { fco_tcv = tv, fco_visL = vL, fco_visR = vR + , fco_kind = k_co, fco_body = co }) + = Just (tv, vL, vR, k_co, co) +splitForAllCo_maybe _ = Nothing -- | Like 'splitForAllCo_maybe', but only returns Just for tyvar binder -splitForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, Coercion, Coercion) -splitForAllCo_ty_maybe (ForAllCo tv k_co co) - | isTyVar tv = Just (tv, k_co, co) +splitForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion) +splitForAllCo_ty_maybe co + | Just stuff@(tv, _, _, _, _) <- splitForAllCo_maybe co + , isTyVar tv + = Just stuff splitForAllCo_ty_maybe _ = Nothing -- | Like 'splitForAllCo_maybe', but only returns Just for covar binder -splitForAllCo_co_maybe :: Coercion -> Maybe (CoVar, Coercion, Coercion) -splitForAllCo_co_maybe (ForAllCo cv k_co co) - | isCoVar cv = Just (cv, k_co, co) +splitForAllCo_co_maybe :: Coercion -> Maybe (CoVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion) +splitForAllCo_co_maybe co + | Just stuff@(cv, _, _, _, _) <- splitForAllCo_maybe co + , isCoVar cv + = Just stuff splitForAllCo_co_maybe _ = Nothing + ------------------------------------------------------- -- and some coercion kind stuff @@ -919,101 +923,86 @@ mkAppCos :: Coercion -> Coercion mkAppCos co1 cos = foldl' mkAppCo co1 cos -{- Note [Unused coercion variable in ForAllCo] - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -See Note [Unused coercion variable in ForAllTy] in GHC.Core.TyCo.Rep for the -motivation for checking coercion variable in types. -To lift the design choice to (ForAllCo cv kind_co body_co), we have two options: - -(1) In mkForAllCo, we check whether cv is a coercion variable - and whether it is not used in body_co. If so we construct a FunCo. -(2) We don't do this check in mkForAllCo. - In coercionKind, we use mkTyCoForAllTy to perform the check and construct - a FunTy when necessary. - -We chose (2) for two reasons: - -* for a coercion, all that matters is its kind, So ForAllCo or FunCo does not - make a difference. -* even if cv occurs in body_co, it is possible that cv does not occur in the kind - of body_co. Therefore the check in coercionKind is inevitable. - -The last wrinkle is that there are restrictions around the use of the cv in the -coercion, as described in Section 5.8.5.2 of Richard's thesis. The idea is that -we cannot prove that the type system is consistent with unrestricted use of this -cv; the consistency proof uses an untyped rewrite relation that works over types -with all coercions and casts removed. So, we can allow the cv to appear only in -positions that are erased. As an approximation of this (and keeping close to the -published theory), we currently allow the cv only within the type in a Refl node -and under a GRefl node (including in the Coercion stored in a GRefl). It's -possible other places are OK, too, but this is a safe approximation. - -Sadly, with heterogeneous equality, this restriction might be able to be violated; -Richard's thesis is unable to prove that it isn't. Specifically, the liftCoSubst -function might create an invalid coercion. Because a violation of the -restriction might lead to a program that "goes wrong", it is checked all the time, -even in a production compiler and without -dcore-lint. We *have* proved that the -problem does not occur with homogeneous equality, so this check can be dropped -once ~# is made to be homogeneous. --} - -- | Make a Coercion from a tycovar, a kind coercion, and a body coercion. --- The kind of the tycovar should be the left-hand kind of the kind coercion. --- See Note [Unused coercion variable in ForAllCo] -mkForAllCo :: TyCoVar -> CoercionN -> Coercion -> Coercion -mkForAllCo v kind_co co - | assert (varType v `eqType` (coercionLKind kind_co)) True - , assert (isTyVar v || almostDevoidCoVarOfCo v co) True - , Just (ty, r) <- isReflCo_maybe co - , isGReflCo kind_co - = mkReflCo r (mkTyCoInvForAllTy v ty) - | otherwise - = ForAllCo v kind_co co +mkForAllCo :: HasDebugCallStack => TyCoVar -> ForAllTyFlag -> ForAllTyFlag -> CoercionN -> Coercion -> Coercion +mkForAllCo v visL visR kind_co co + | Just (ty, r) <- isReflCo_maybe co + , isReflCo kind_co + , visL `eqForAllVis` visR + = mkReflCo r (mkTyCoForAllTy v visL ty) --- | Like 'mkForAllCo', but the inner coercion shouldn't be an obvious --- reflexive coercion. For example, it is guaranteed in 'mkForAllCos'. --- The kind of the tycovar should be the left-hand kind of the kind coercion. -mkForAllCo_NoRefl :: TyCoVar -> CoercionN -> Coercion -> Coercion -mkForAllCo_NoRefl v kind_co co - | assert (varType v `eqType` (coercionLKind kind_co)) True - , assert (not (isReflCo co)) True - , isCoVar v - , assert (almostDevoidCoVarOfCo v co) True - , not (v `elemVarSet` tyCoVarsOfCo co) - = mkFunCoNoFTF (coercionRole co) (multToCo ManyTy) kind_co co - -- Functions from coercions are always unrestricted - | otherwise - = ForAllCo v kind_co co - --- | Make nested ForAllCos -mkForAllCos :: [(TyCoVar, CoercionN)] -> Coercion -> Coercion -mkForAllCos bndrs co - | Just (ty, r ) <- isReflCo_maybe co - = let (refls_rev'd, non_refls_rev'd) = span (isReflCo . snd) (reverse bndrs) in - foldl' (flip $ uncurry mkForAllCo_NoRefl) - (mkReflCo r (mkTyCoInvForAllTys (reverse (map fst refls_rev'd)) ty)) - non_refls_rev'd | otherwise - = foldr (uncurry mkForAllCo_NoRefl) co bndrs + = mkForAllCo_NoRefl v visL visR kind_co co -- | Make a Coercion quantified over a type/coercion variable; --- the variable has the same type in both sides of the coercion -mkHomoForAllCos :: [TyCoVar] -> Coercion -> Coercion -mkHomoForAllCos vs co - | Just (ty, r) <- isReflCo_maybe co - = mkReflCo r (mkTyCoInvForAllTys vs ty) +-- the variable has the same kind and visibility in both sides of the coercion +mkHomoForAllCos :: [ForAllTyBinder] -> Coercion -> Coercion +mkHomoForAllCos vs orig_co + | Just (ty, r) <- isReflCo_maybe orig_co + = mkReflCo r (mkTyCoForAllTys vs ty) + | otherwise + = foldr go orig_co vs + where + go (Bndr var vis) co + = mkForAllCo_NoRefl var vis vis (mkNomReflCo (varType var)) co + +-- | Like 'mkForAllCo', but there is no need to check that the inner coercion isn't Refl; +-- the caller has done that. (For example, it is guaranteed in 'mkHomoForAllCos'.) +-- The kind of the tycovar should be the left-hand kind of the kind coercion. +mkForAllCo_NoRefl :: TyCoVar -> ForAllTyFlag -> ForAllTyFlag -> CoercionN -> Coercion -> Coercion +mkForAllCo_NoRefl tcv visL visR kind_co co + = assertGoodForAllCo tcv visL visR kind_co co $ + assertPpr (not (isReflCo co && isReflCo kind_co && visL == visR)) (ppr co) $ + ForAllCo { fco_tcv = tcv, fco_visL = visL, fco_visR = visR + , fco_kind = kind_co, fco_body = co } + +assertGoodForAllCo :: HasDebugCallStack + => TyCoVar -> ForAllTyFlag -> ForAllTyFlag + -> CoercionN -> Coercion -> a -> a +-- Check ForAllCo invariants; see Note [ForAllCo] in GHC.Core.TyCo.Rep +assertGoodForAllCo tcv visL visR kind_co co + | isTyVar tcv + = assertPpr (tcv_type `eqType` kind_co_lkind) doc + | otherwise - = mkHomoForAllCos_NoRefl vs co - --- | Like 'mkHomoForAllCos', but the inner coercion shouldn't be an obvious --- reflexive coercion. For example, it is guaranteed in 'mkHomoForAllCos'. -mkHomoForAllCos_NoRefl :: [TyCoVar] -> Coercion -> Coercion -mkHomoForAllCos_NoRefl vs orig_co - = assert (not (isReflCo orig_co)) - foldr go orig_co vs + = assertPpr (tcv_type `eqType` kind_co_lkind) doc + -- The kind of the tycovar should be the left-hand kind of the kind coercion. + . assertPpr (almostDevoidCoVarOfCo tcv co) doc + -- See (FC6) in Note [ForAllCo] in GHC.Core.TyCo.Rep + . assertPpr (visL == coreTyLamForAllTyFlag + && visR == coreTyLamForAllTyFlag) doc + -- See (FC7) in Note [ForAllCo] in GHC.Core.TyCo.Rep where - go v co = mkForAllCo_NoRefl v (mkNomReflCo (varType v)) co + tcv_type = varType tcv + kind_co_lkind = coercionLKind kind_co + + doc = vcat [ text "Var:" <+> ppr tcv <+> dcolon <+> ppr tcv_type + , text "Vis:" <+> ppr visL <+> ppr visR + , text "kind_co:" <+> ppr kind_co + , text "kind_co_lkind" <+> ppr kind_co_lkind + , text "body_co" <+> ppr co ] + + +mkNakedForAllCo :: TyVar -- Never a CoVar + -> ForAllTyFlag -> ForAllTyFlag + -> CoercionN -> Coercion -> Coercion +-- This version lacks the assertion checks. +-- Used during type checking when the arguments may (legitimately) not be zonked +-- and so the assertions might (bogusly) fail +-- NB: since the coercions are un-zonked, we can't really deal with +-- (FC6) and (FC7) in Note [ForAllCo] in GHC.Core.TyCo.Rep. +-- Fortunately we don't have to: this function is needed only for /type/ variables. +mkNakedForAllCo tv visL visR kind_co co + | assertPpr (isTyVar tv) (ppr tv) True + , Just (ty, r) <- isReflCo_maybe co + , isReflCo kind_co + , visL `eqForAllVis` visR + = mkReflCo r (mkForAllTy (Bndr tv visL) ty) + | otherwise + = ForAllCo { fco_tcv = tv, fco_visL = visL, fco_visR = visR + , fco_kind = kind_co, fco_body = co } + mkCoVarCo :: CoVar -> Coercion -- cv :: s ~# t @@ -1163,7 +1152,7 @@ mkSelCo_maybe cs co | Just (ty, r) <- isReflCo_maybe co = Just (mkReflCo r (getNthFromType cs ty)) - go SelForAll (ForAllCo _ kind_co _) + go SelForAll (ForAllCo { fco_kind = kind_co }) = Just kind_co -- If co :: (forall a1:k1. t1) ~ (forall a2:k2. t2) -- then (nth SelForAll co :: k1 ~N k2) @@ -1231,7 +1220,7 @@ mkLRCo lr co -- | Instantiates a 'Coercion'. mkInstCo :: Coercion -> CoercionN -> Coercion -mkInstCo (ForAllCo tcv _kind_co body_co) co +mkInstCo (ForAllCo { fco_tcv = tcv, fco_body = body_co }) co | Just (arg, _) <- isReflCo_maybe co -- works for both tyvar and covar = substCoUnchecked (zipTCvSubst [tcv] [arg]) body_co @@ -1383,8 +1372,10 @@ setNominalRole_maybe r co = TransCo <$> setNominalRole_maybe_helper co1 <*> setNominalRole_maybe_helper co2 setNominalRole_maybe_helper (AppCo co1 co2) = AppCo <$> setNominalRole_maybe_helper co1 <*> pure co2 - setNominalRole_maybe_helper (ForAllCo tv kind_co co) - = ForAllCo tv kind_co <$> setNominalRole_maybe_helper co + setNominalRole_maybe_helper co@(ForAllCo { fco_visL = visL, fco_visR = visR, fco_body = body_co }) + | visL `eqForAllVis` visR -- See (FC3) in Note [ForAllCo] in GHC.Core.TyCo.Rep + = do { body_co' <- setNominalRole_maybe_helper body_co + ; return (co { fco_body = body_co' }) } setNominalRole_maybe_helper (SelCo cs co) = -- NB, this case recurses via setNominalRole_maybe, not -- setNominalRole_maybe_helper! @@ -1404,6 +1395,7 @@ setNominalRole_maybe r co | case prov of PhantomProv _ -> False -- should always be phantom ProofIrrelProv _ -> True -- it's always safe PluginProv _ -> False -- who knows? This choice is conservative. + CorePrepProv _ -> True = Just $ UnivCo prov Nominal co1 co2 setNominalRole_maybe_helper _ = Nothing @@ -1474,7 +1466,7 @@ ltRole Nominal _ = True -- | like mkKindCo, but aggressively & recursively optimizes to avoid using -- a KindCo constructor. The output role is nominal. -promoteCoercion :: Coercion -> CoercionN +promoteCoercion :: HasDebugCallStack => Coercion -> CoercionN -- First cases handles anything that should yield refl. promoteCoercion co = case co of @@ -1504,7 +1496,7 @@ promoteCoercion co = case co of | otherwise -> mkKindCo co - ForAllCo tv _ g + ForAllCo { fco_tcv = tv, fco_body = g } | isTyVar tv -> promoteCoercion g @@ -1515,7 +1507,7 @@ promoteCoercion co = case co of -- a coercion variable. So both sides have kind Type -- (Note [Weird typing rule for ForAllTy] in GHC.Core.TyCo.Rep). -- So the result is Refl, and that should have been caught by - -- the first equation above + -- the first equation above. Hence `assert False` mkNomReflCo liftedTypeKind FunCo {} -> mkKindCo co @@ -1659,7 +1651,7 @@ mkPiCos r vs co = foldr (mkPiCo r) co vs -- | Make a forall 'Coercion', where both types related by the coercion -- are quantified over the same variable. mkPiCo :: Role -> Var -> Coercion -> Coercion -mkPiCo r v co | isTyVar v = mkHomoForAllCos [v] co +mkPiCo r v co | isTyVar v = mkHomoForAllCos [Bndr v coreTyLamForAllTyFlag] co | isCoVar v = assert (not (v `elemVarSet` tyCoVarsOfCo co)) $ -- We didn't call mkForAllCo here because if v does not appear -- in co, the argument coercion will be nominal. But here we @@ -2083,17 +2075,17 @@ ty_co_subst !lc role ty go r (AppTy ty1 ty2) = mkAppCo (go r ty1) (go Nominal ty2) go r (TyConApp tc tys) = mkTyConAppCo r tc (zipWith go (tyConRoleListX r tc) tys) go r (FunTy af w t1 t2) = mkFunCo r af (go Nominal w) (go r t1) (go r t2) - go r t@(ForAllTy (Bndr v _) ty) + go r t@(ForAllTy (Bndr v vis) ty) = let (lc', v', h) = liftCoSubstVarBndr lc v body_co = ty_co_subst lc' r ty in if isTyVar v' || almostDevoidCoVarOfCo v' body_co -- Lifting a ForAllTy over a coercion variable could fail as ForAllCo - -- imposes an extra restriction on where a covar can appear. See last - -- wrinkle in Note [Unused coercion variable in ForAllCo]. - -- We specifically check for this and panic because we know that - -- there's a hole in the type system here, and we'd rather panic than - -- fall into it. - then mkForAllCo v' h body_co + -- imposes an extra restriction on where a covar can appear. See + -- (FC6) of Note [ForAllCo] in GHC.Tc.TyCo.Rep + -- We specifically check for this and panic because we know that + -- there's a hole in the type system here (see (FC6), and we'd rather + -- panic than fall into it. + then mkForAllCo v' vis vis h body_co else pprPanic "ty_co_subst: covar is not almost devoid" (ppr t) go r ty@(LitTy {}) = assert (r == Nominal) $ mkNomReflCo ty @@ -2331,8 +2323,9 @@ seqCo (Refl ty) = seqType ty seqCo (GRefl r ty mco) = r `seq` seqType ty `seq` seqMCo mco seqCo (TyConAppCo r tc cos) = r `seq` tc `seq` seqCos cos seqCo (AppCo co1 co2) = seqCo co1 `seq` seqCo co2 -seqCo (ForAllCo tv k co) = seqType (varType tv) `seq` seqCo k - `seq` seqCo co +seqCo (ForAllCo tv visL visR k co) = seqType (varType tv) `seq` + rnf visL `seq` rnf visR `seq` + seqCo k `seq` seqCo co seqCo (FunCo r af1 af2 w co1 co2) = r `seq` af1 `seq` af2 `seq` seqCo w `seq` seqCo co1 `seq` seqCo co2 seqCo (CoVarCo cv) = cv `seq` () @@ -2397,7 +2390,8 @@ coercionLKind co go (GRefl _ ty _) = ty go (TyConAppCo _ tc cos) = mkTyConApp tc (map go cos) go (AppCo co1 co2) = mkAppTy (go co1) (go co2) - go (ForAllCo tv1 _ co1) = mkTyCoInvForAllTy tv1 (go co1) + go (ForAllCo { fco_tcv = tv1, fco_visL = visL, fco_body = co1 }) + = mkTyCoForAllTy tv1 visL (go co1) go (FunCo { fco_afl = af, fco_mult = mult, fco_arg = arg, fco_res = res}) {- See Note [FunCo] -} = FunTy { ft_af = af, ft_mult = go mult , ft_arg = go arg, ft_res = go res } @@ -2476,8 +2470,9 @@ coercionRKind co go (AxiomRuleCo ax cos) = pSnd $ expectJust "coercionKind" $ coaxrProves ax $ map coercionKind cos - go co@(ForAllCo tv1 k_co co1) -- works for both tyvar and covar - | isGReflCo k_co = mkTyCoInvForAllTy tv1 (go co1) + go co@(ForAllCo { fco_tcv = tv1, fco_visR = visR + , fco_kind = k_co, fco_body = co1 }) -- works for both tyvar and covar + | isGReflCo k_co = mkTyCoForAllTy tv1 visR (go co1) -- kind_co always has kind @Type@, thus @isGReflCo@ | otherwise = go_forall empty_subst co where @@ -2500,10 +2495,11 @@ coercionRKind co go_app (InstCo co arg) args = go_app co (go arg:args) go_app co args = piResultTys (go co) args - go_forall subst (ForAllCo tv1 k_co co) + go_forall subst (ForAllCo { fco_tcv = tv1, fco_visR = visR + , fco_kind = k_co, fco_body = co }) -- See Note [Nested ForAllCos] | isTyVar tv1 - = mkInfForAllTy tv2 (go_forall subst' co) + = mkForAllTy (Bndr tv2 visR) (go_forall subst' co) where k2 = coercionRKind k_co tv2 = setTyVarKind tv1 (substTy subst k2) @@ -2512,9 +2508,10 @@ coercionRKind co | otherwise = extendTvSubst (extendSubstInScope subst tv2) tv1 $ TyVarTy tv2 `mkCastTy` mkSymCo k_co - go_forall subst (ForAllCo cv1 k_co co) + go_forall subst (ForAllCo { fco_tcv = cv1, fco_visR = visR + , fco_kind = k_co, fco_body = co }) | isCoVar cv1 - = mkTyCoInvForAllTy cv2 (go_forall subst' co) + = mkTyCoForAllTy cv2 visR (go_forall subst' co) where k2 = coercionRKind k_co r = coVarRole cv1 @@ -2562,26 +2559,26 @@ change reduces /total/ compile time by a factor of more than ten. coercionRole :: Coercion -> Role coercionRole = go where - go (Refl _) = Nominal - go (GRefl r _ _) = r - go (TyConAppCo r _ _) = r - go (AppCo co1 _) = go co1 - go (ForAllCo _ _ co) = go co - go (FunCo { fco_role = r }) = r - go (CoVarCo cv) = coVarRole cv - go (HoleCo h) = coVarRole (coHoleCoVar h) - go (AxiomInstCo ax _ _) = coAxiomRole ax - go (UnivCo _ r _ _) = r - go (SymCo co) = go co - go (TransCo co1 _co2) = go co1 - go (SelCo SelForAll _co) = Nominal - go (SelCo (SelTyCon _ r) _co) = r - go (SelCo (SelFun fs) co) = funRole (coercionRole co) fs - go (LRCo {}) = Nominal - go (InstCo co _) = go co - go (KindCo {}) = Nominal - go (SubCo _) = Representational - go (AxiomRuleCo ax _) = coaxrRole ax + go (Refl _) = Nominal + go (GRefl r _ _) = r + go (TyConAppCo r _ _) = r + go (AppCo co1 _) = go co1 + go (ForAllCo { fco_body = co }) = go co + go (FunCo { fco_role = r }) = r + go (CoVarCo cv) = coVarRole cv + go (HoleCo h) = coVarRole (coHoleCoVar h) + go (AxiomInstCo ax _ _) = coAxiomRole ax + go (UnivCo _ r _ _) = r + go (SymCo co) = go co + go (TransCo co1 _co2) = go co1 + go (SelCo SelForAll _co) = Nominal + go (SelCo (SelTyCon _ r) _co) = r + go (SelCo (SelFun fs) co) = funRole (coercionRole co) fs + go (LRCo {}) = Nominal + go (InstCo co _) = go co + go (KindCo {}) = Nominal + go (SubCo _) = Representational + go (AxiomRuleCo ax _) = coaxrRole ax {- Note [Nested InstCos] @@ -2686,19 +2683,19 @@ buildCoercion orig_ty1 orig_ty2 = go orig_ty1 orig_ty2 | Just (ty1a, ty1b) <- splitAppTyNoView_maybe ty1 = mkAppCo (go ty1a ty2a) (go ty1b ty2b) - go (ForAllTy (Bndr tv1 _flag1) ty1) (ForAllTy (Bndr tv2 _flag2) ty2) + go (ForAllTy (Bndr tv1 flag1) ty1) (ForAllTy (Bndr tv2 flag2) ty2) | isTyVar tv1 = assert (isTyVar tv2) $ - mkForAllCo tv1 kind_co (go ty1 ty2') + mkForAllCo tv1 flag1 flag2 kind_co (go ty1 ty2') where kind_co = go (tyVarKind tv1) (tyVarKind tv2) in_scope = mkInScopeSet $ tyCoVarsOfType ty2 `unionVarSet` tyCoVarsOfCo kind_co ty2' = substTyWithInScope in_scope [tv2] [mkTyVarTy tv1 `mkCastTy` kind_co] ty2 - go (ForAllTy (Bndr cv1 _flag1) ty1) (ForAllTy (Bndr cv2 _flag2) ty2) + go (ForAllTy (Bndr cv1 flag1) ty1) (ForAllTy (Bndr cv2 flag2) ty2) = assert (isCoVar cv1 && isCoVar cv2) $ - mkForAllCo cv1 kind_co (go ty1 ty2') + mkForAllCo cv1 flag1 flag2 kind_co (go ty1 ty2') where s1 = varType cv1 s2 = varType cv2 kind_co = go s1 s2 diff --git a/compiler/GHC/Core/Coercion.hs-boot b/compiler/GHC/Core/Coercion.hs-boot index 276a48cf81811e3ad8afba8f22be01d67aaea1bd..b2a11c603da7812c61e6a6a49820e42096dd397e 100644 --- a/compiler/GHC/Core/Coercion.hs-boot +++ b/compiler/GHC/Core/Coercion.hs-boot @@ -16,7 +16,7 @@ import GHC.Utils.Misc mkReflCo :: Role -> Type -> Coercion mkTyConAppCo :: HasDebugCallStack => Role -> TyCon -> [Coercion] -> Coercion mkAppCo :: Coercion -> Coercion -> Coercion -mkForAllCo :: TyCoVar -> Coercion -> Coercion -> Coercion +mkForAllCo :: HasDebugCallStack => TyCoVar -> ForAllTyFlag -> ForAllTyFlag -> Coercion -> Coercion -> Coercion mkFunCo :: Role -> FunTyFlag -> CoercionN -> Coercion -> Coercion -> Coercion mkNakedFunCo :: Role -> FunTyFlag -> CoercionN -> Coercion -> Coercion -> Coercion mkFunCo2 :: Role -> FunTyFlag -> FunTyFlag -> CoercionN -> Coercion -> Coercion -> Coercion diff --git a/compiler/GHC/Core/Coercion/Opt.hs b/compiler/GHC/Core/Coercion/Opt.hs index 98506c444e323fea25d972c220916be0138cb8d5..44a381259801ac697dd8c2142eb384523fb71544 100644 --- a/compiler/GHC/Core/Coercion/Opt.hs +++ b/compiler/GHC/Core/Coercion/Opt.hs @@ -14,13 +14,14 @@ import GHC.Tc.Utils.TcType ( exactTyCoVarsOfType ) import GHC.Core.TyCo.Rep import GHC.Core.TyCo.Subst -import GHC.Core.TyCo.Compare( eqType ) +import GHC.Core.TyCo.Compare( eqType, eqForAllVis ) import GHC.Core.Coercion import GHC.Core.Type as Type hiding( substTyVarBndr, substTy ) import GHC.Core.TyCon import GHC.Core.Coercion.Axiom import GHC.Core.Unify +import GHC.Types.Var import GHC.Types.Var.Set import GHC.Types.Var.Env import GHC.Types.Unique.Set @@ -289,11 +290,14 @@ opt_co4 env sym rep r (AppCo co1 co2) = mkAppCo (opt_co4_wrap env sym rep r co1) (opt_co4_wrap env sym False Nominal co2) -opt_co4 env sym rep r (ForAllCo tv k_co co) +opt_co4 env sym rep r (ForAllCo { fco_tcv = tv, fco_visL = visL, fco_visR = visR + , fco_kind = k_co, fco_body = co }) = case optForAllCoBndr env sym tv k_co of - (env', tv', k_co') -> mkForAllCo tv' k_co' $ + (env', tv', k_co') -> mkForAllCo tv' visL' visR' k_co' $ opt_co4_wrap env' sym rep r co -- Use the "mk" functions to check for nested Refls + where + !(visL', visR') = swapSym sym (visL, visR) opt_co4 env sym rep r (FunCo _r afl afr cow co1 co2) = assert (r == _r) $ @@ -304,8 +308,7 @@ opt_co4 env sym rep r (FunCo _r afl afr cow co1 co2) cow' = opt_co1 env sym cow !r' | rep = Representational | otherwise = r - !(afl', afr') | sym = (afr,afl) - | otherwise = (afl,afr) + !(afl', afr') = swapSym sym (afl, afr) opt_co4 env sym rep r (CoVarCo cv) | Just co <- lookupCoVar (lcSubst env) cv @@ -375,7 +378,7 @@ opt_co4 env sym rep r (SelCo (SelTyCon n r1) (TyConAppCo _ _ cos)) opt_co4 env sym rep r (SelCo (SelFun fs) (FunCo _r2 _afl _afr w co1 co2)) = opt_co4_wrap env sym rep r (getNthFun fs w co1 co2) -opt_co4 env sym rep _ (SelCo SelForAll (ForAllCo _ eta _)) +opt_co4 env sym rep _ (SelCo SelForAll (ForAllCo { fco_kind = eta })) -- works for both tyvar and covar = opt_co4_wrap env sym rep Nominal eta @@ -383,7 +386,7 @@ opt_co4 env sym rep r (SelCo n co) | Just nth_co <- case (co', n) of (TyConAppCo _ _ cos, SelTyCon n _) -> Just (cos `getNth` n) (FunCo _ _ _ w co1 co2, SelFun fs) -> Just (getNthFun fs w co1 co2) - (ForAllCo _ eta _, SelForAll) -> Just eta + (ForAllCo { fco_kind = eta }, SelForAll) -> Just eta _ -> Nothing = if rep && (r == Nominal) -- keep propagating the SubCo @@ -415,7 +418,7 @@ opt_co4 env sym rep r (LRCo lr co) -- See Note [Optimising InstCo] opt_co4 env sym rep r (InstCo co1 arg) -- forall over type... - | Just (tv, kind_co, co_body) <- splitForAllCo_ty_maybe co1 + | Just (tv, _visL, _visR, kind_co, co_body) <- splitForAllCo_ty_maybe co1 = opt_co4_wrap (extendLiftingContext env tv (mkCoherenceRightCo Nominal t2 (mkSymCo kind_co) sym_arg)) -- mkSymCo kind_co :: k1 ~ k2 @@ -424,7 +427,7 @@ opt_co4 env sym rep r (InstCo co1 arg) sym rep r co_body -- forall over coercion... - | Just (cv, kind_co, co_body) <- splitForAllCo_co_maybe co1 + | Just (cv, _visL, _visR, kind_co, co_body) <- splitForAllCo_co_maybe co1 , CoercionTy h1 <- t1 , CoercionTy h2 <- t2 = let new_co = mk_new_co cv (opt_co4_wrap env sym False Nominal kind_co) h1 h2 @@ -434,13 +437,13 @@ opt_co4 env sym rep r (InstCo co1 arg) -- If so, do an inefficient one-variable substitution, then re-optimize -- forall over type... - | Just (tv', kind_co', co_body') <- splitForAllCo_ty_maybe co1' + | Just (tv', _visL, _visR, kind_co', co_body') <- splitForAllCo_ty_maybe co1' = opt_co4_wrap (extendLiftingContext (zapLiftingContext env) tv' (mkCoherenceRightCo Nominal t2' (mkSymCo kind_co') arg')) False False r' co_body' -- forall over coercion... - | Just (cv', kind_co', co_body') <- splitForAllCo_co_maybe co1' + | Just (cv', _visL, _visR, kind_co', co_body') <- splitForAllCo_co_maybe co1' , CoercionTy h1' <- t1' , CoercionTy h2' <- t2' = let new_co = mk_new_co cv' kind_co' h1' h2' @@ -574,8 +577,10 @@ opt_univ env sym prov role oty1 oty2 -- can't optimize the AppTy case because we can't build the kind coercions. - | Just (tv1, ty1) <- splitForAllTyVar_maybe oty1 - , Just (tv2, ty2) <- splitForAllTyVar_maybe oty2 + | Just (Bndr tv1 vis1, ty1) <- splitForAllForAllTyBinder_maybe oty1 + , isTyVar tv1 + , Just (Bndr tv2 vis2, ty2) <- splitForAllForAllTyBinder_maybe oty2 + , isTyVar tv2 -- NB: prov isn't interesting here either = let k1 = tyVarKind tv1 k2 = tyVarKind tv2 @@ -584,11 +589,14 @@ opt_univ env sym prov role oty1 oty2 ty2' = substTyWith [tv2] [TyVarTy tv1 `mkCastTy` eta] ty2 (env', tv1', eta') = optForAllCoBndr env sym tv1 eta + !(vis1', vis2') = swapSym sym (vis1, vis2) in - mkForAllCo tv1' eta' (opt_univ env' sym prov' role ty1 ty2') + mkForAllCo tv1' vis1' vis2' eta' (opt_univ env' sym prov' role ty1 ty2') - | Just (cv1, ty1) <- splitForAllCoVar_maybe oty1 - , Just (cv2, ty2) <- splitForAllCoVar_maybe oty2 + | Just (Bndr cv1 vis1, ty1) <- splitForAllForAllTyBinder_maybe oty1 + , isCoVar cv1 + , Just (Bndr cv2 vis2, ty2) <- splitForAllForAllTyBinder_maybe oty2 + , isCoVar cv2 -- NB: prov isn't interesting here either = let k1 = varType cv1 k2 = varType cv2 @@ -602,8 +610,9 @@ opt_univ env sym prov role oty1 oty2 ty2' = substTyWithCoVars [cv2] [n_co] ty2 (env', cv1', eta') = optForAllCoBndr env sym cv1 eta + !(vis1', vis2') = swapSym sym (vis1, vis2) in - mkForAllCo cv1' eta' (opt_univ env' sym prov' role ty1 ty2') + mkForAllCo cv1' vis1' vis2' eta' (opt_univ env' sym prov' role ty1 ty2') | otherwise = let ty1 = substTyUnchecked (lcSubstLeft env) oty1 @@ -747,23 +756,23 @@ opt_trans_rule is co1 co2@(AppCo co2a co2b) -- Push transitivity inside forall -- forall over types. opt_trans_rule is co1 co2 - | Just (tv1, eta1, r1) <- splitForAllCo_ty_maybe co1 - , Just (tv2, eta2, r2) <- etaForAllCo_ty_maybe co2 - = push_trans tv1 eta1 r1 tv2 eta2 r2 + | Just (tv1, visL1, _visR1, eta1, r1) <- splitForAllCo_ty_maybe co1 + , Just (tv2, _visL2, visR2, eta2, r2) <- etaForAllCo_ty_maybe co2 + = push_trans tv1 eta1 r1 tv2 eta2 r2 visL1 visR2 - | Just (tv2, eta2, r2) <- splitForAllCo_ty_maybe co2 - , Just (tv1, eta1, r1) <- etaForAllCo_ty_maybe co1 - = push_trans tv1 eta1 r1 tv2 eta2 r2 + | Just (tv2, _visL2, visR2, eta2, r2) <- splitForAllCo_ty_maybe co2 + , Just (tv1, visL1, _visR1, eta1, r1) <- etaForAllCo_ty_maybe co1 + = push_trans tv1 eta1 r1 tv2 eta2 r2 visL1 visR2 where - push_trans tv1 eta1 r1 tv2 eta2 r2 + push_trans tv1 eta1 r1 tv2 eta2 r2 visL visR -- Given: - -- co1 = /\ tv1 : eta1. r1 - -- co2 = /\ tv2 : eta2. r2 + -- co1 = /\ tv1 : eta1 <visL, visM>. r1 + -- co2 = /\ tv2 : eta2 <visM, visR>. r2 -- Wanted: - -- /\tv1 : (eta1;eta2). (r1; r2[tv2 |-> tv1 |> eta1]) + -- /\tv1 : (eta1;eta2) <visL, visR>. (r1; r2[tv2 |-> tv1 |> eta1]) = fireTransRule "EtaAllTy_ty" co1 co2 $ - mkForAllCo tv1 (opt_trans is eta1 eta2) (opt_trans is' r1 r2') + mkForAllCo tv1 visL visR (opt_trans is eta1 eta2) (opt_trans is' r1 r2') where is' = is `extendInScopeSet` tv1 r2' = substCoWithUnchecked [tv2] [mkCastTy (TyVarTy tv1) eta1] r2 @@ -771,25 +780,25 @@ opt_trans_rule is co1 co2 -- Push transitivity inside forall -- forall over coercions. opt_trans_rule is co1 co2 - | Just (cv1, eta1, r1) <- splitForAllCo_co_maybe co1 - , Just (cv2, eta2, r2) <- etaForAllCo_co_maybe co2 - = push_trans cv1 eta1 r1 cv2 eta2 r2 + | Just (cv1, visL1, _visR1, eta1, r1) <- splitForAllCo_co_maybe co1 + , Just (cv2, _visL2, visR2, eta2, r2) <- etaForAllCo_co_maybe co2 + = push_trans cv1 eta1 r1 cv2 eta2 r2 visL1 visR2 - | Just (cv2, eta2, r2) <- splitForAllCo_co_maybe co2 - , Just (cv1, eta1, r1) <- etaForAllCo_co_maybe co1 - = push_trans cv1 eta1 r1 cv2 eta2 r2 + | Just (cv2, _visL2, visR2, eta2, r2) <- splitForAllCo_co_maybe co2 + , Just (cv1, visL1, _visR1, eta1, r1) <- etaForAllCo_co_maybe co1 + = push_trans cv1 eta1 r1 cv2 eta2 r2 visL1 visR2 where - push_trans cv1 eta1 r1 cv2 eta2 r2 + push_trans cv1 eta1 r1 cv2 eta2 r2 visL visR -- Given: - -- co1 = /\ cv1 : eta1. r1 - -- co2 = /\ cv2 : eta2. r2 + -- co1 = /\ (cv1 : eta1) <visL, visM>. r1 + -- co2 = /\ (cv2 : eta2) <visM, visR>. r2 -- Wanted: -- n1 = nth 2 eta1 -- n2 = nth 3 eta1 -- nco = /\ cv1 : (eta1;eta2). (r1; r2[cv2 |-> (sym n1);cv1;n2]) = fireTransRule "EtaAllTy_co" co1 co2 $ - mkForAllCo cv1 (opt_trans is eta1 eta2) (opt_trans is' r1 r2') + mkForAllCo cv1 visL visR (opt_trans is eta1 eta2) (opt_trans is' r1 r2') where is' = is `extendInScopeSet` cv1 role = coVarRole cv1 @@ -1087,6 +1096,10 @@ The problem described here was first found in dependent/should_compile/dynamic-p -} ----------- +swapSym :: SymFlag -> (a,a) -> (a,a) +swapSym sym (x,y) | sym = (y,x) + | otherwise = (x,y) + wrapSym :: SymFlag -> Coercion -> Coercion wrapSym sym co | sym = mkSymCo co | otherwise = co @@ -1186,31 +1199,39 @@ Here, eta2 = mkSelCo (SelTyCon 3 r) h1 :: (s2 ~ s4) h2 = mkInstCo g (cv1 ~ (sym eta1;c1;eta2)) -} -etaForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, Coercion, Coercion) +etaForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion) -- Try to make the coercion be of form (forall tv:kind_co. co) etaForAllCo_ty_maybe co - | Just (tv, kind_co, r) <- splitForAllCo_ty_maybe co - = Just (tv, kind_co, r) - - | Pair ty1 ty2 <- coercionKind co - , Just (tv1, _) <- splitForAllTyVar_maybe ty1 - , isForAllTy_ty ty2 + | Just (tv, visL, visR, kind_co, r) <- splitForAllCo_ty_maybe co + = Just (tv, visL, visR, kind_co, r) + + | (Pair ty1 ty2, role) <- coercionKindRole co + , Just (Bndr tv1 vis1, _) <- splitForAllForAllTyBinder_maybe ty1 + , isTyVar tv1 + , Just (Bndr tv2 vis2, _) <- splitForAllForAllTyBinder_maybe ty2 + , isTyVar tv2 + -- can't eta-expand at nominal role unless visibilities match + , (role /= Nominal) || (vis1 `eqForAllVis` vis2) , let kind_co = mkSelCo SelForAll co - = Just ( tv1, kind_co + = Just ( tv1, vis1, vis2, kind_co , mkInstCo co (mkGReflRightCo Nominal (TyVarTy tv1) kind_co)) | otherwise = Nothing -etaForAllCo_co_maybe :: Coercion -> Maybe (CoVar, Coercion, Coercion) +etaForAllCo_co_maybe :: Coercion -> Maybe (CoVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion) -- Try to make the coercion be of form (forall cv:kind_co. co) etaForAllCo_co_maybe co - | Just (cv, kind_co, r) <- splitForAllCo_co_maybe co - = Just (cv, kind_co, r) - - | Pair ty1 ty2 <- coercionKind co - , Just (cv1, _) <- splitForAllCoVar_maybe ty1 - , isForAllTy_co ty2 + | Just (cv, visL, visR, kind_co, r) <- splitForAllCo_co_maybe co + = Just (cv, visL, visR, kind_co, r) + + | (Pair ty1 ty2, role) <- coercionKindRole co + , Just (Bndr cv1 vis1, _) <- splitForAllForAllTyBinder_maybe ty1 + , isCoVar cv1 + , Just (Bndr cv2 vis2, _) <- splitForAllForAllTyBinder_maybe ty2 + , isCoVar cv2 + -- can't eta-expand at nominal role unless visibilities match + , (role /= Nominal) = let kind_co = mkSelCo SelForAll co r = coVarRole cv1 l_co = mkCoVarCo cv1 @@ -1218,7 +1239,7 @@ etaForAllCo_co_maybe co r_co = mkSymCo (mkSelCo (SelTyCon 2 r) kind_co') `mkTransCo` l_co `mkTransCo` mkSelCo (SelTyCon 3 r) kind_co' - in Just ( cv1, kind_co + in Just ( cv1, vis1, vis2, kind_co , mkInstCo co (mkProofIrrelCo Nominal kind_co l_co r_co)) | otherwise diff --git a/compiler/GHC/Core/FVs.hs b/compiler/GHC/Core/FVs.hs index 175091086d327adf8cb2f2168e79841b0164aa0d..225bc05960297712d8e09adf1198a937e632277b 100644 --- a/compiler/GHC/Core/FVs.hs +++ b/compiler/GHC/Core/FVs.hs @@ -386,8 +386,9 @@ orphNamesOfCo (Refl ty) = orphNamesOfType ty orphNamesOfCo (GRefl _ ty mco) = orphNamesOfType ty `unionNameSet` orphNamesOfMCo mco orphNamesOfCo (TyConAppCo _ tc cos) = unitNameSet (getName tc) `unionNameSet` orphNamesOfCos cos orphNamesOfCo (AppCo co1 co2) = orphNamesOfCo co1 `unionNameSet` orphNamesOfCo co2 -orphNamesOfCo (ForAllCo _ kind_co co) = orphNamesOfCo kind_co - `unionNameSet` orphNamesOfCo co +orphNamesOfCo (ForAllCo { fco_kind = kind_co, fco_body = co }) + = orphNamesOfCo kind_co + `unionNameSet` orphNamesOfCo co orphNamesOfCo (FunCo { fco_mult = co_mult, fco_arg = co1, fco_res = co2 }) = orphNamesOfCo co_mult `unionNameSet` orphNamesOfCo co1 diff --git a/compiler/GHC/Core/Lint.hs b/compiler/GHC/Core/Lint.hs index 1dd782172bea9d8d1c80ce65337c4d32812c45fd..bc49d1183620b4dccc9ea1be42477b970d21380f 100644 --- a/compiler/GHC/Core/Lint.hs +++ b/compiler/GHC/Core/Lint.hs @@ -48,7 +48,7 @@ import GHC.Core.Type as Type import GHC.Core.Multiplicity import GHC.Core.UsageEnv import GHC.Core.TyCo.Rep -- checks validity of types/coercions -import GHC.Core.TyCo.Compare( eqType ) +import GHC.Core.TyCo.Compare ( eqType, eqForAllVis ) import GHC.Core.TyCo.Subst import GHC.Core.TyCo.FVs import GHC.Core.TyCo.Ppr @@ -1842,7 +1842,6 @@ lintType ty@(ForAllTy (Bndr tcv vis) body_ty) lintL (tcv `elemVarSet` tyCoVarsOfType body_ty) $ text "Covar does not occur in the body:" <+> (ppr tcv $$ ppr body_ty) -- See GHC.Core.TyCo.Rep Note [Unused coercion variable in ForAllTy] - -- and cf GHC.Core.Coercion Note [Unused coercion variable in ForAllCo] ; return (ForAllTy (Bndr tcv' vis) body_ty') } @@ -2230,9 +2229,14 @@ lintCoercion co@(AppCo co1 co2) ; return (AppCo co1' co2') } ---------- -lintCoercion co@(ForAllCo tcv kind_co body_co) +lintCoercion co@(ForAllCo { fco_tcv = tcv, fco_visL = visL, fco_visR = visR + , fco_kind = kind_co, fco_body = body_co }) +-- See Note [ForAllCo] in GHC.Core.TyCo.Rep, +-- including the typing rule for ForAllCo + | not (isTyCoVar tcv) = failWithL (text "Non tyco binder in ForAllCo:" <+> ppr co) + | otherwise = do { kind_co' <- lintStarCoercion kind_co ; lintTyCoBndr tcv $ \tcv' -> @@ -2246,18 +2250,24 @@ lintCoercion co@(ForAllCo tcv kind_co body_co) -- (forall (tcv:k2). rty[(tcv:k2) |> sym kind_co/tcv]) -- are both well formed. Easiest way is to call lintForAllBody -- for each; there is actually no need to do the funky substitution - ; let Pair lty rty = coercionKind body_co' + ; let (Pair lty rty, body_role) = coercionKindRole body_co' ; lintForAllBody tcv' lty ; lintForAllBody tcv' rty ; when (isCoVar tcv) $ - lintL (almostDevoidCoVarOfCo tcv body_co) $ - text "Covar can only appear in Refl and GRefl: " <+> ppr co - -- See "last wrinkle" in GHC.Core.Coercion - -- Note [Unused coercion variable in ForAllCo] - -- and c.f. GHC.Core.TyCo.Rep Note [Unused coercion variable in ForAllTy] + do { lintL (visL == coreTyLamForAllTyFlag && visR == coreTyLamForAllTyFlag) $ + text "Invalid visibility flags in CoVar ForAllCo" <+> ppr co + -- See (FC7) in Note [ForAllCo] in GHC.Core.TyCo.Rep + ; lintL (almostDevoidCoVarOfCo tcv body_co) $ + text "Covar can only appear in Refl and GRefl: " <+> ppr co + -- See (FC6) in Note [ForAllCo] in GHC.Core.TyCo.Rep + } + + ; when (body_role == Nominal) $ + lintL (visL `eqForAllVis` visR) $ + text "Nominal ForAllCo has mismatched visibilities: " <+> ppr co - ; return (ForAllCo tcv' kind_co' body_co') } } + ; return (co { fco_tcv = tcv', fco_kind = kind_co', fco_body = body_co' }) } } lintCoercion co@(FunCo { fco_role = r, fco_afl = afl, fco_afr = afr , fco_mult = cow, fco_arg = co1, fco_res = co2 }) diff --git a/compiler/GHC/Core/Opt/Arity.hs b/compiler/GHC/Core/Opt/Arity.hs index 85309063698ee7033ed52146c36b28400d4af10b..c3d5ea41c3f9d62bc86d38339aa65accff1b5fdd 100644 --- a/compiler/GHC/Core/Opt/Arity.hs +++ b/compiler/GHC/Core/Opt/Arity.hs @@ -68,6 +68,7 @@ import GHC.Core.TyCo.Compare( eqType ) import GHC.Types.Demand import GHC.Types.Cpr( CprSig, mkCprSig, botCpr ) import GHC.Types.Id +import GHC.Types.Var import GHC.Types.Var.Env import GHC.Types.Var.Set import GHC.Types.Basic @@ -2037,8 +2038,8 @@ This what eta_expand does. We do it in two steps: Note that the /same/ EtaInfo drives both etaInfoAbs and etaInfoApp -To a first approximation EtaInfo is just [Var]. But -casts complicate the question. If we have +To a first approximation EtaInfo is just [Var]. But casts complicate +the question. If we have newtype N a = MkN (S -> a) axN :: N a ~ S -> a and @@ -2054,6 +2055,20 @@ nested newtypes. This is expressed by the EtaInfo type: data EtaInfo = EI [Var] MCoercionR +Precisely, here is the (EtaInfo Invariant): + + EI bs co :: EtaInfo + +describes a particular eta-expansion, thus: + + Abstraction: (\b1 b2 .. bn. []) |> sym co + Application: ([] |> co) b1 b2 .. bn + + e :: T + co :: T ~R (t1 -> t2 -> .. -> tn -> tr) + e = (\b1 b2 ... bn. (e |> co) b1 b2 .. bn) |> sym co + + Note [Check for reflexive casts in eta expansion] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It turns out that the casts created by the above mechanism are often Refl. @@ -2109,13 +2124,7 @@ Now, when we push that eta_co inward in etaInfoApp: -------------- data EtaInfo = EI [Var] MCoercionR - --- (EI bs co) describes a particular eta-expansion, as follows: --- Abstraction: (\b1 b2 .. bn. []) |> sym co --- Application: ([] |> co) b1 b2 .. bn --- --- e :: T co :: T ~ (t1 -> t2 -> .. -> tn -> tr) --- e = (\b1 b2 ... bn. (e |> co) b1 b2 .. bn) |> sym co + -- See Note [The EtaInfo mechanism] instance Outputable EtaInfo where ppr (EI vs mco) = text "EI" <+> ppr vs <+> parens (ppr mco) @@ -2229,14 +2238,14 @@ mkEtaWW orig_oss ppr_orig_expr in_scope orig_ty go n oss@(one_shot:oss1) subst ty ----------- Forall types (forall a. ty) - | Just (tcv,ty') <- splitForAllTyCoVar_maybe ty + | Just (Bndr tcv vis, ty') <- splitForAllForAllTyBinder_maybe ty , (subst', tcv') <- Type.substVarBndr subst tcv , let oss' | isTyVar tcv = oss | otherwise = oss1 -- A forall can bind a CoVar, in which case -- we consume one of the [OneShotInfo] , (in_scope, EI bs mco) <- go n oss' subst' ty' - = (in_scope, EI (tcv' : bs) (mkHomoForAllMCo tcv' mco)) + = (in_scope, EI (tcv' : bs) (mkEtaForAllMCo (Bndr tcv' vis) ty' mco)) ----------- Function types (t1 -> t2) | Just (_af, mult, arg_ty, res_ty) <- splitFunTy_maybe ty @@ -2279,6 +2288,19 @@ mkEtaWW orig_oss ppr_orig_expr in_scope orig_ty -- So we simply decline to eta-expand. Otherwise we'd end up -- with an explicit lambda having a non-function type +mkEtaForAllMCo :: ForAllTyBinder -> Type -> MCoercion -> MCoercion +mkEtaForAllMCo (Bndr tcv vis) ty mco + = case mco of + MRefl | vis == coreTyLamForAllTyFlag -> MRefl + | otherwise -> mk_fco (mkRepReflCo ty) + MCo co -> mk_fco co + where + mk_fco co = MCo (mkForAllCo tcv vis coreTyLamForAllTyFlag + (mkNomReflCo (varType tcv)) co) + -- coreTyLamForAllTyFlag: See Note [The EtaInfo mechanism], particularly + -- the (EtaInfo Invariant). (sym co) wraps a lambda that always has + -- a ForAllTyFlag of coreTyLamForAllTyFlag; see wrinkle (FC4) in + -- Note [ForAllCo] in GHC.Core.TyCo.Rep {- ************************************************************************ @@ -2706,9 +2728,14 @@ tryEtaReduce rec_ids bndrs body eval_sd -- (and similarly for tyvars, coercion args) , [CoreTickish]) -- See Note [Eta reduction with casted arguments] - ok_arg bndr (Type ty) co _ - | Just tv <- getTyVar_maybe ty - , bndr == tv = Just (mkHomoForAllCos [tv] co, []) + ok_arg bndr (Type arg_ty) co fun_ty + | Just tv <- getTyVar_maybe arg_ty + , bndr == tv = case splitForAllForAllTyBinder_maybe fun_ty of + Just (Bndr _ vis, _) -> Just (mkHomoForAllCos [Bndr tv vis] co, []) + Nothing -> pprPanic "tryEtaReduce: type arg to non-forall type" + (text "fun:" <+> ppr bndr + $$ text "arg:" <+> ppr arg_ty + $$ text "fun_ty:" <+> ppr fun_ty) ok_arg bndr (Var v) co fun_ty | bndr == v , let mult = idMult bndr diff --git a/compiler/GHC/Core/Reduction.hs b/compiler/GHC/Core/Reduction.hs index a4f1df4f703d6c1d99a493c61d62d32cc6d3726b..71402aa383cb7eee33b56793110cc50cdb3a984d 100644 --- a/compiler/GHC/Core/Reduction.hs +++ b/compiler/GHC/Core/Reduction.hs @@ -376,7 +376,7 @@ mkForAllRedn :: ForAllTyFlag -> Reduction mkForAllRedn vis tv1 (Reduction h ki') (Reduction co ty) = mkReduction - (mkForAllCo tv1 h co) + (mkForAllCo tv1 vis vis h co) (mkForAllTy (Bndr tv2 vis) ty) where tv2 = setTyVarKind tv1 ki' @@ -389,7 +389,7 @@ mkForAllRedn vis tv1 (Reduction h ki') (Reduction co ty) mkHomoForAllRedn :: [TyVarBinder] -> Reduction -> Reduction mkHomoForAllRedn bndrs (Reduction co ty) = mkReduction - (mkHomoForAllCos (binderVars bndrs) co) + (mkHomoForAllCos bndrs co) (mkForAllTys bndrs ty) {-# INLINE mkHomoForAllRedn #-} diff --git a/compiler/GHC/Core/TyCo/Compare.hs b/compiler/GHC/Core/TyCo/Compare.hs index c0a87d34ffb363b52acc03eb186df8e496b1f451..b03729e21c256b5880ba7836daa00532e8bbf595 100644 --- a/compiler/GHC/Core/TyCo/Compare.hs +++ b/compiler/GHC/Core/TyCo/Compare.hs @@ -173,7 +173,7 @@ tc_eq_type keep_syns vis_only orig_ty1 orig_ty2 go env (ForAllTy (Bndr tv1 vis1) ty1) (ForAllTy (Bndr tv2 vis2) ty2) - = vis1 `eqForAllVis` vis2 + = vis1 `eqForAllVis` vis2 -- See Note [ForAllTy and type equality] && (vis_only || go env (varType tv1) (varType tv2)) && go (rnBndr2 env tv1 tv2) ty1 ty2 @@ -230,7 +230,6 @@ tc_eq_type keep_syns vis_only orig_ty1 orig_ty2 -- equates 'Specified' and 'Inferred'. Used for printing. eqForAllVis :: ForAllTyFlag -> ForAllTyFlag -> Bool -- See Note [ForAllTy and type equality] --- If you change this, see IMPORTANT NOTE in the above Note eqForAllVis Required Required = True eqForAllVis (Invisible _) (Invisible _) = True eqForAllVis _ _ = False @@ -240,7 +239,6 @@ eqForAllVis _ _ = False -- equates 'Specified' and 'Inferred'. Used for printing. cmpForAllVis :: ForAllTyFlag -> ForAllTyFlag -> Ordering -- See Note [ForAllTy and type equality] --- If you change this, see IMPORTANT NOTE in the above Note cmpForAllVis Required Required = EQ cmpForAllVis Required (Invisible {}) = LT cmpForAllVis (Invisible _) Required = GT @@ -251,12 +249,58 @@ cmpForAllVis (Invisible _) (Invisible _) = EQ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When we compare (ForAllTy (Bndr tv1 vis1) ty1) and (ForAllTy (Bndr tv2 vis2) ty2) -what should we do about `vis1` vs `vis2`. - -First, we always compare with `eqForAllVis` and `cmpForAllVis`. -But what decision do we make? - -Should GHC type-check the following program (adapted from #15740)? +what should we do about `vis1` vs `vis2`? + +We had a long debate about this: see #22762 and GHC Proposal 558. +Here is the conclusion. + +* In Haskell, we really do want (forall a. ty) and (forall a -> ty) to be + distinct types, not interchangeable. The latter requires a type argument, + but the former does not. See GHC Proposal 558. + +* We /really/ do not want the typechecker and Core to have different notions of + equality. That is, we don't want `tcEqType` and `eqType` to differ. Why not? + Not so much because of code duplication but because it is virtually impossible + to cleave the two apart. Here is one particularly awkward code path: + The type checker calls `substTy`, which calls `mkAppTy`, + which calls `mkCastTy`, which calls `isReflexiveCo`, which calls `eqType`. + +* Moreover the resolution of the TYPE vs CONSTRAINT story was to make the + typechecker and Core have a single notion of equality. + +* So in GHC: + - `tcEqType` and `eqType` implement the same equality + - (forall a. ty) and (forall a -> ty) are distinct types in both Core and typechecker + - That is, both `eqType` and `tcEqType` distinguish them. + +* But /at representational role/ we can relate the types. That is, + (forall a. ty) ~R (forall a -> ty) + After all, since types are erased, they are represented the same way. + See Note [ForAllCo] and the typing rule for ForAllCo given there + +* What about (forall a. ty) and (forall {a}. ty)? See Note [Comparing visibility]. + +Note [Comparing visibility] +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We are sure that we want to distinguish (forall a. ty) and (forall a -> ty); see +Note [ForAllTy and type equality]. But we have /three/ settings for the ForAllTyFlag: + * Specified: forall a. ty + * Inferred: forall {a}. ty + * Required: forall a -> ty + +We could (and perhaps should) distinguish all three. But for now we distinguish +Required from Specified/Inferred, and ignore the distinction between Specified +and Inferred. + +The answer doesn't matter too much, provided we are consistent. And we are consistent +because we always compare ForAllTyFlags with + * `eqForAllVis` + * `cmpForAllVis`. +(You can only really check this by inspecting all pattern matches on ForAllTyFlags.) +So if we change the decision, we just need to change those functions. + +Why don't we distinguish all three? Should GHC type-check the following program +(adapted from #15740)? {-# LANGUAGE PolyKinds, ... #-} data D a @@ -303,15 +347,11 @@ That is, we have the following: | | forall k -> <...> | Yes | -------------------------------------------------- -IMPORTANT NOTE: if we want to change this decision, ForAllCo will need to carry -visiblity (by taking a ForAllTyBinder rathre than a TyCoVar), so that -coercionLKind/RKind build forall types that match (are equal to) the desired -ones. Otherwise we get an infinite loop in the solver via canEqCanLHSHetero. Examples: T16946, T15079. Historical Note [Typechecker equality vs definitional equality] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This Note describes some history, in case there are vesitges of this +This Note describes some history, in case there are vestiges of this history lying around in the code. Summary: prior to summer 2022, GHC had have two notions of equality @@ -514,7 +554,7 @@ nonDetCmpTypeX env orig_t1 orig_t2 = go env (TyVarTy tv1) (TyVarTy tv2) = liftOrdering $ rnOccL env tv1 `nonDetCmpVar` rnOccR env tv2 go env (ForAllTy (Bndr tv1 vis1) t1) (ForAllTy (Bndr tv2 vis2) t2) - = liftOrdering (vis1 `cmpForAllVis` vis2) + = liftOrdering (vis1 `cmpForAllVis` vis2) -- See Note [ForAllTy and type equality] `thenCmpTy` go env (varType tv1) (varType tv2) `thenCmpTy` go (rnBndr2 env tv1 tv2) t1 t2 diff --git a/compiler/GHC/Core/TyCo/FVs.hs b/compiler/GHC/Core/TyCo/FVs.hs index aa9c04c46bfaa3840e95475125091d1bf3f2a8b8..3dd1759a347a529061c3cd713cc55f86f700666b 100644 --- a/compiler/GHC/Core/TyCo/FVs.hs +++ b/compiler/GHC/Core/TyCo/FVs.hs @@ -631,7 +631,7 @@ tyCoFVsOfCo (GRefl _ ty mco) fv_cand in_scope acc tyCoFVsOfCo (TyConAppCo _ _ cos) fv_cand in_scope acc = tyCoFVsOfCos cos fv_cand in_scope acc tyCoFVsOfCo (AppCo co arg) fv_cand in_scope acc = (tyCoFVsOfCo co `unionFV` tyCoFVsOfCo arg) fv_cand in_scope acc -tyCoFVsOfCo (ForAllCo tv kind_co co) fv_cand in_scope acc +tyCoFVsOfCo (ForAllCo { fco_tcv = tv, fco_kind = kind_co, fco_body = co }) fv_cand in_scope acc = (tyCoFVsVarBndr tv (tyCoFVsOfCo co) `unionFV` tyCoFVsOfCo kind_co) fv_cand in_scope acc tyCoFVsOfCo (FunCo { fco_mult = w, fco_arg = co1, fco_res = co2 }) fv_cand in_scope acc = (tyCoFVsOfCo co1 `unionFV` tyCoFVsOfCo co2 `unionFV` tyCoFVsOfCo w) fv_cand in_scope acc @@ -672,7 +672,7 @@ tyCoFVsOfCos (co:cos) fv_cand in_scope acc = (tyCoFVsOfCo co `unionFV` tyCoFVsOf -- | Given a covar and a coercion, returns True if covar is almost devoid in -- the coercion. That is, covar can only appear in Refl and GRefl. --- See last wrinkle in Note [Unused coercion variable in ForAllCo] in "GHC.Core.Coercion" +-- See (FC6) in Note [ForAllCo] in "GHC.Core.TyCo.Rep" almostDevoidCoVarOfCo :: CoVar -> Coercion -> Bool almostDevoidCoVarOfCo cv co = almost_devoid_co_var_of_co co cv @@ -686,7 +686,7 @@ almost_devoid_co_var_of_co (TyConAppCo _ _ cos) cv almost_devoid_co_var_of_co (AppCo co arg) cv = almost_devoid_co_var_of_co co cv && almost_devoid_co_var_of_co arg cv -almost_devoid_co_var_of_co (ForAllCo v kind_co co) cv +almost_devoid_co_var_of_co (ForAllCo { fco_tcv = v, fco_kind = kind_co, fco_body = co }) cv = almost_devoid_co_var_of_co kind_co cv && (v == cv || almost_devoid_co_var_of_co co cv) almost_devoid_co_var_of_co (FunCo { fco_mult = w, fco_arg = co1, fco_res = co2 }) cv @@ -1109,7 +1109,8 @@ tyConsOfType ty go_co (GRefl _ ty mco) = go ty `unionUniqSets` go_mco mco go_co (TyConAppCo _ tc args) = go_tc tc `unionUniqSets` go_cos args go_co (AppCo co arg) = go_co co `unionUniqSets` go_co arg - go_co (ForAllCo _ kind_co co) = go_co kind_co `unionUniqSets` go_co co + go_co (ForAllCo { fco_kind = kind_co, fco_body = co }) + = go_co kind_co `unionUniqSets` go_co co go_co (FunCo { fco_mult = m, fco_arg = a, fco_res = r }) = go_co m `unionUniqSets` go_co a `unionUniqSets` go_co r go_co (AxiomInstCo ax _ args) = go_ax ax `unionUniqSets` go_cos args @@ -1293,14 +1294,14 @@ occCheckExpand vs_to_avoid ty go_co cxt (AppCo co arg) = do { co' <- go_co cxt co ; arg' <- go_co cxt arg ; return (AppCo co' arg') } - go_co cxt@(as, env) (ForAllCo tv kind_co body_co) + go_co cxt@(as, env) co@(ForAllCo { fco_tcv = tv, fco_kind = kind_co, fco_body = body_co }) = do { kind_co' <- go_co cxt kind_co ; let tv' = setVarType tv $ coercionLKind kind_co' env' = extendVarEnv env tv tv' as' = as `delVarSet` tv ; body' <- go_co (as', env') body_co - ; return (ForAllCo tv' kind_co' body') } + ; return (co { fco_tcv = tv', fco_kind = kind_co', fco_body = body' }) } go_co cxt co@(FunCo { fco_mult = w, fco_arg = co1 ,fco_res = co2 }) = do { co1' <- go_co cxt co1 ; co2' <- go_co cxt co2 diff --git a/compiler/GHC/Core/TyCo/FVs.hs-boot b/compiler/GHC/Core/TyCo/FVs.hs-boot index bc890c9784655d51c8e0fa2d0bd93a57ebeb8222..af9555fdec672c4884f62cd038b53df4200c3964 100644 --- a/compiler/GHC/Core/TyCo/FVs.hs-boot +++ b/compiler/GHC/Core/TyCo/FVs.hs-boot @@ -1,6 +1,8 @@ module GHC.Core.TyCo.FVs where import GHC.Prelude ( Bool ) +import GHC.Types.Var.Set( TyCoVarSet ) import {-# SOURCE #-} GHC.Core.TyCo.Rep ( Type ) noFreeVarsOfType :: Type -> Bool +tyCoVarsOfType :: Type -> TyCoVarSet \ No newline at end of file diff --git a/compiler/GHC/Core/TyCo/Rep.hs b/compiler/GHC/Core/TyCo/Rep.hs index 245a1c507b89bd5569590a1af2ecd89c5c792c3e..af86de998f5bd70068f2337f301e1ab7044443cb 100644 --- a/compiler/GHC/Core/TyCo/Rep.hs +++ b/compiler/GHC/Core/TyCo/Rep.hs @@ -71,12 +71,14 @@ import GHC.Prelude import {-# SOURCE #-} GHC.Core.TyCo.Ppr ( pprType, pprCo, pprTyLit ) import {-# SOURCE #-} GHC.Builtin.Types +import {-# SOURCE #-} GHC.Core.TyCo.FVs( tyCoVarsOfType ) -- Use in assertions import {-# SOURCE #-} GHC.Core.Type( chooseFunTyFlag, typeKind, typeTypeOrConstraint ) -- Transitively pulls in a LOT of stuff, better to break the loop -- friends: import GHC.Types.Var +import GHC.Types.Var.Set( elemVarSet ) import GHC.Core.TyCon import GHC.Core.Coercion.Axiom @@ -152,13 +154,13 @@ data Type -- for example unsaturated type synonyms -- can appear as the right hand side of a type synonym. - | ForAllTy + | ForAllTy -- See Note [ForAllTy] {-# UNPACK #-} !ForAllTyBinder Type -- ^ A Î type. - -- Note [When we quantify over a coercion variable] + -- See Note [Why ForAllTy can quantify over a coercion variable] -- INVARIANT: If the binder is a coercion variable, it must - -- be mentioned in the Type. See - -- Note [Unused coercion variable in ForAllTy] + -- be mentioned in the Type. + -- See Note [Unused coercion variable in ForAllTy] | FunTy -- ^ FUN m t1 t2 Very common, so an important special case -- See Note [Function types] @@ -452,7 +454,7 @@ to differ, leading to a contradiction. Thus, co is reflexive. Accordingly, by eliminating reflexive casts, splitTyConApp need not worry about outermost casts to uphold (EQ). Eliminating reflexive casts is done -in mkCastTy. This is (EQ1) below. +in mkCastTy. This is (EQ2) below. Unfortunately, that's not the end of the story. Consider comparing (T a b c) =? (T a b |> (co -> <Type>)) (c |> co) @@ -475,7 +477,7 @@ our (EQ) property. In order to detect reflexive casts reliably, we must make sure not to have nested casts: we update (t |> co1 |> co2) to (t |> (co1 `TransCo` co2)). -This is (EQ2) below. +This is (EQ3) below. One other troublesome case is ForAllTy. See Note [Weird typing rule for ForAllTy]. The kind of the body is the same as the kind of the ForAllTy. Accordingly, @@ -488,9 +490,9 @@ This is done in mkCastTy. In sum, in order to uphold (EQ), we need the following invariants: - (EQ1) No decomposable CastTy to the left of an AppTy, where a decomposable - cast is one that relates either a FunTy to a FunTy or a - ForAllTy to a ForAllTy. + (EQ1) No decomposable CastTy to the left of an AppTy, + where a "decomposable cast" is one that relates + either a FunTy to a FunTy, or a ForAllTy to a ForAllTy. (EQ2) No reflexive casts in CastTy. (EQ3) No nested CastTys. (EQ4) No CastTy over (ForAllTy (Bndr tyvar vis) body). @@ -517,8 +519,22 @@ In order to compare FunTys while respecting how they could expand into TyConApps, we must check the kinds of the arg and the res. -Note [When we quantify over a coercion variable] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note [ForAllTy] +~~~~~~~~~~~~~~~ +A (ForAllTy (Bndr tcv vis) ty) can quantify over a TyVar or, less commonly, a CoVar. +See Note [Why ForAllTy can quantify over a coercion variable] for why we need the latter. + +(FT1) Invariant: See Note [Weird typing rule for ForAllTy] + +(FT2) Invariant: in (ForAllTy (Bndr tcv vis) ty), + if tcv is a CoVar, then vis = coreTyLamForAllTyFlag. + Visibility is not important for coercion abstractions, + because they are not user-visible. + +(FT3) Invariant: see Note [Unused coercion variable in ForAllTy] + +Note [Why ForAllTy can quantify over a coercion variable] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ForAllTyBinder in a ForAllTy can be (most often) a TyVar or (rarely) a CoVar. We support quantifying over a CoVar here in order to support a homogeneous (~#) relation (someday -- not yet implemented). Here is @@ -541,10 +557,8 @@ Note that we must cast `a` by a cv bound in the same type in order to make this work out. See also https://gitlab.haskell.org/ghc/ghc/-/wikis/dependent-haskell/phase2 -which gives a general road map that covers this space. - -Having this feature in Core does *not* mean we have it in source Haskell. -See #15710 about that. +which gives a general road map that covers this space. Having this feature in +Core does *not* mean we have it in source Haskell. See #15710 about that. Note [Unused coercion variable in ForAllTy] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -775,7 +789,17 @@ tcMkScaledFunTys tys ty = foldr mk ty tys -- | Like 'mkTyCoForAllTy', but does not check the occurrence of the binder -- See Note [Unused coercion variable in ForAllTy] mkForAllTy :: ForAllTyBinder -> Type -> Type -mkForAllTy = ForAllTy +mkForAllTy bndr body + = assertPpr (good_bndr bndr) (ppr bndr <+> ppr body) $ + ForAllTy bndr body + where + -- Check ForAllTy invariants + good_bndr (Bndr cv vis) + | isCoVar cv = vis == coreTyLamForAllTyFlag + -- See (FT2) in Note [ForAllTy] + && (cv `elemVarSet` tyCoVarsOfType body) + -- See (FT3) in Note [ForAllTy] + | otherwise = True -- | Wraps foralls over the type using the provided 'TyCoVar's from left to right mkForAllTys :: [ForAllTyBinder] -> Type -> Type @@ -849,8 +873,14 @@ data Coercion | AppCo Coercion CoercionN -- lift AppTy -- AppCo :: e -> N -> e - -- See Note [Forall coercions] - | ForAllCo TyCoVar KindCoercion Coercion + -- See Note [ForAllCo] + | ForAllCo + { fco_tcv :: TyCoVar + , fco_visL :: !ForAllTyFlag -- Visibility of coercionLKind + , fco_visR :: !ForAllTyFlag -- Visibility of coercionRKind + -- See (FC7) of Note [ForAllCo] + , fco_kind :: KindCoercion + , fco_body :: Coercion } -- ForAllCo :: _ -> N -> e -> e | FunCo -- FunCo :: "e" -> N/P -> e -> e -> e @@ -1159,43 +1189,105 @@ among branches, but that doesn't quite concern us here.) The Int in the AxiomInstCo constructor is the 0-indexed number of the chosen branch. -Note [Forall coercions] -~~~~~~~~~~~~~~~~~~~~~~~ +Note [ForAllCo] +~~~~~~~~~~~~~~~ +See also Note [ForAllTy and type equality] in GHC.Core.TyCo.Compare. + Constructing coercions between forall-types can be a bit tricky, because the kinds of the bound tyvars can be different. The typing rule is: - - kind_co : k1 ~ k2 - tv1:k1 |- co : t1 ~ t2 - ------------------------------------------------------------------- - ForAllCo tv1 kind_co co : all tv1:k1. t1 ~ - all tv1:k2. (t2[tv1 |-> tv1 |> sym kind_co]) - -First, the TyCoVar stored in a ForAllCo is really an optimisation: this field -should be a Name, as its kind is redundant. Thinking of the field as a Name -is helpful in understanding what a ForAllCo means. -The kind of TyCoVar always matches the left-hand kind of the coercion. - -The idea is that kind_co gives the two kinds of the tyvar. See how, in the -conclusion, tv1 is assigned kind k1 on the left but kind k2 on the right. - -Of course, a type variable can't have different kinds at the same time. So, -we arbitrarily prefer the first kind when using tv1 in the inner coercion -co, which shows that t1 equals t2. - -The last wrinkle is that we need to fix the kinds in the conclusion. In -t2, tv1 is assumed to have kind k1, but it has kind k2 in the conclusion of -the rule. So we do a kind-fixing substitution, replacing (tv1:k1) with -(tv1:k2) |> sym kind_co. This substitution is slightly bizarre, because it -mentions the same name with different kinds, but it *is* well-kinded, noting -that `(tv1:k2) |> sym kind_co` has kind k1. - -This all really would work storing just a Name in the ForAllCo. But we can't -add Names to, e.g., VarSets, and there generally is just an impedance mismatch -in a bunch of places. So we use tv1. When we need tv2, we can use -setTyVarKind. + kind_co : k1 ~N k2 + tv1:k1 |- co : t1 ~r t2 + if r=N, then vis1=vis2 + ------------------------------------ + ForAllCo (tv1:k1) vis1 vis2 kind_co co + : forall (tv1:k1) <vis1>. t1 + ~r + forall (tv1:k2) <vis2>. (t2[tv1 |-> (tv1:k2) |> sym kind_co]) + +Several things to note here + +(FC1) First, the TyCoVar stored in a ForAllCo is really just a convenience: this + field should be a Name, as its kind is redundant. Thinking of the field as a + Name is helpful in understanding what a ForAllCo means. The kind of TyCoVar + always matches the left-hand kind of the coercion. + + * The idea is that kind_co gives the two kinds of the tyvar. See how, in the + conclusion, tv1 is assigned kind k1 on the left but kind k2 on the right. + + * Of course, a type variable can't have different kinds at the same time. + So, in `co` itself we use (tv1 : k1); hence the premise + tv1:k1 |- co : t1 ~r t2 + + * The last wrinkle is that we need to fix the kinds in the conclusion. In + t2, tv1 is assumed to have kind k1, but it has kind k2 in the conclusion of + the rule. So we do a kind-fixing substitution, replacing (tv1:k1) with + (tv1:k2) |> sym kind_co. This substitution is slightly bizarre, because it + mentions the same name with different kinds, but it *is* well-kinded, noting + that `(tv1:k2) |> sym kind_co` has kind k1. + + We could instead store just a Name in the ForAllCo, and it might even be + more efficient to do so. But we can't add Names to, e.g., VarSets, and + there generally is just an impedance mismatch in a bunch of places. So we + use tv1. When we need tv2, we can use setTyVarKind. + +(FC2) Note that the kind coercion must be Nominal; and that the role `r` of + the final coercion is the same as that of the body coercion. + +(FC3) A ForAllCo allows casting between visibilities. For example: + ForAllCo a Required Specified (SubCo (Refl ty)) + : (forall a -> ty) ~R (forall a. ty) + But you can only cast between visiblities at Representational role; + Hence the premise + if r=N, then vis1=vis2 + in the typing rule. See also Note [ForAllTy and type equality] in + GHC.Core.TyCo.Compare. + +(FC4) A lambda term (Lam a e) has type (forall a. ty), with visibility + flag `GHC.Type.Var.coreTyLamForAllTyFlag`, not (forall a -> ty). + See `GHC.Type.Var.coreTyLamForAllTyFlag` and `GHC.Core.Utils.mkLamType`. + The only way to get a term of type (forall a -> ty) is to cast a lambda. + +(FC5) In a /type/, in (ForAllTy cv ty) where cv is a CoVar, we insist that + `cv` must appear free in `ty`; see Note [Unused coercion variable in ForAllTy] + in GHC.Core.TyCo.Rep for the motivation. If it does not appear free, + use FunTy. + + However we do /not/ impose the same restriction on ForAllCo in /coercions/. + Instead, in coercionLKind and coercionRKind, we use mkTyCoForAllTy to perform + the check and construct a FunTy when necessary. Why? + * For a coercion, all that matters is its kind, So ForAllCo vs FunCo does not + make a difference. + * Even if cv occurs in body_co, it is possible that cv does not occur in the kind + of body_co. Therefore the check in coercionKind is inevitable. + +(FC6) Invariant: in a ForAllCo where fco_tcv is a coercion variable, `cv`, + we insist that `cv` appears only in positions that are erased. In fact we use + a conservative approximation of this: we require that + (almostDevoidCoVarOfCo cv fco_body) + holds. This function checks that `cv` appers only within the type in a Refl + node and under a GRefl node (including in the Coercion stored in a GRefl). + It's possible other places are OK, too, but this is a safe approximation. + + Why all this fuss? See Section 5.8.5.2 of Richard's thesis. The idea is that + we cannot prove that the type system is consistent with unrestricted use of this + cv; the consistency proof uses an untyped rewrite relation that works over types + with all coercions and casts removed. So, we can allow the cv to appear only in + positions that are erased. + + Sadly, with heterogeneous equality, this restriction might be able to be + violated; Richard's thesis is unable to prove that it isn't. Specifically, the + liftCoSubst function might create an invalid coercion. Because a violation of + the restriction might lead to a program that "goes wrong", it is checked all + the time, even in a production compiler and without -dcore-lint. We *have* + proved that the problem does not occur with homogeneous equality, so this + check can be dropped once ~# is made to be homogeneous. + +(FC7) Invariant: in a ForAllCo, if fco_tcv is a CoVar, then + fco_visL = fco_visR = coreTyLamForAllTyFlag + c.f. (FT2) in Note [ForAllTy] Note [Predicate coercions] ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1760,7 +1852,7 @@ foldTyCo (TyCoFolder { tcf_view = view go_co env (FunCo { fco_mult = cw, fco_arg = c1, fco_res = c2 }) = go_co env cw `mappend` go_co env c1 `mappend` go_co env c2 - go_co env (ForAllCo tv kind_co co) + go_co env (ForAllCo tv _vis1 _vis2 kind_co co) = go_co env kind_co `mappend` go_ty env (varType tv) `mappend` go_co env' co where @@ -1815,7 +1907,8 @@ coercionSize (GRefl _ ty MRefl) = typeSize ty coercionSize (GRefl _ ty (MCo co)) = 1 + typeSize ty + coercionSize co coercionSize (TyConAppCo _ _ args) = 1 + sum (map coercionSize args) coercionSize (AppCo co arg) = coercionSize co + coercionSize arg -coercionSize (ForAllCo _ h co) = 1 + coercionSize co + coercionSize h +coercionSize (ForAllCo { fco_kind = h, fco_body = co }) + = 1 + coercionSize co + coercionSize h coercionSize (FunCo _ _ _ w c1 c2) = 1 + coercionSize c1 + coercionSize c2 + coercionSize w coercionSize (CoVarCo _) = 1 diff --git a/compiler/GHC/Core/TyCo/Subst.hs b/compiler/GHC/Core/TyCo/Subst.hs index 4224bd127bc39aed9c7afd4b5af23ff401b3dac3..c867ed2e76f8b1104f2b2547b0ec910a765259b0 100644 --- a/compiler/GHC/Core/TyCo/Subst.hs +++ b/compiler/GHC/Core/TyCo/Subst.hs @@ -535,7 +535,8 @@ Note [Sym and ForAllCo] In OptCoercion, we try to push "sym" out to the leaves of a coercion. But, how do we push sym into a ForAllCo? It's a little ugly. -Here is the typing rule: +Ignoring visibility, here is the typing rule +(see Note [ForAllCo] in GHC.Core.TyCo.Rep). h : k1 ~# k2 (tv : k1) |- g : ty1 ~# ty2 @@ -889,10 +890,10 @@ subst_co subst co go (TyConAppCo r tc args)= let args' = map go args in args' `seqList` mkTyConAppCo r tc args' go (AppCo co arg) = (mkAppCo $! go co) $! go arg - go (ForAllCo tv kind_co co) + go (ForAllCo tv visL visR kind_co co) = case substForAllCoBndrUnchecked subst tv kind_co of (subst', tv', kind_co') -> - ((mkForAllCo $! tv') $! kind_co') $! subst_co subst' co + ((mkForAllCo $! tv') visL visR $! kind_co') $! subst_co subst' co go (FunCo r afl afr w co1 co2) = ((mkFunCo2 r afl afr $! go w) $! go co1) $! go co2 go (CoVarCo cv) = substCoVar subst cv go (AxiomInstCo con ind cos) = mkAxiomInstCo con ind $! map go cos diff --git a/compiler/GHC/Core/TyCo/Tidy.hs b/compiler/GHC/Core/TyCo/Tidy.hs index bfd7e4c7ccb0e3b72957fabd8a5c690113e1056c..e5e091a30af9a0297196ec2361260996acaee748 100644 --- a/compiler/GHC/Core/TyCo/Tidy.hs +++ b/compiler/GHC/Core/TyCo/Tidy.hs @@ -228,7 +228,8 @@ tidyCo env@(_, subst) co go (GRefl r ty mco) = (GRefl r $! tidyType env ty) $! go_mco mco go (TyConAppCo r tc cos) = TyConAppCo r tc $! strictMap go cos go (AppCo co1 co2) = (AppCo $! go co1) $! go co2 - go (ForAllCo tv h co) = ((ForAllCo $! tvp) $! (go h)) $! (tidyCo envp co) + go (ForAllCo tv visL visR h co) + = ((((ForAllCo $! tvp) $! visL) $! visR) $! (go h)) $! (tidyCo envp co) where (envp, tvp) = tidyVarBndr env tv -- the case above duplicates a bit of work in tidying h and the kind -- of tv. But the alternative is to use coercionKind, which seems worse. diff --git a/compiler/GHC/Core/Type.hs b/compiler/GHC/Core/Type.hs index 447b77eaae5863f39fff1a21ae982267027235e5..0adf4cc74e72173f8ebf189555957899bb589b2a 100644 --- a/compiler/GHC/Core/Type.hs +++ b/compiler/GHC/Core/Type.hs @@ -48,11 +48,11 @@ module GHC.Core.Type ( mkForAllTy, mkForAllTys, mkInvisForAllTys, mkTyCoInvForAllTys, mkSpecForAllTy, mkSpecForAllTys, - mkVisForAllTys, mkTyCoInvForAllTy, + mkVisForAllTys, mkTyCoForAllTy, mkTyCoForAllTys, mkTyCoInvForAllTy, mkInfForAllTy, mkInfForAllTys, splitForAllTyCoVars, splitForAllTyVars, splitForAllReqTyBinders, splitForAllInvisTyBinders, - splitForAllForAllTyBinders, + splitForAllForAllTyBinders, splitForAllForAllTyBinder_maybe, splitForAllTyCoVar_maybe, splitForAllTyCoVar, splitForAllTyVar_maybe, splitForAllCoVar_maybe, splitPiTy_maybe, splitPiTy, splitPiTys, @@ -549,9 +549,10 @@ expandTypeSynonyms ty = mkTyConAppCo r tc (map (go_co subst) args) go_co subst (AppCo co arg) = mkAppCo (go_co subst co) (go_co subst arg) - go_co subst (ForAllCo tv kind_co co) + go_co subst (ForAllCo { fco_tcv = tv, fco_visL = visL, fco_visR = visR + , fco_kind = kind_co, fco_body = co }) = let (subst', tv', kind_co') = go_cobndr subst tv kind_co in - mkForAllCo tv' kind_co' (go_co subst' co) + mkForAllCo tv' visL visR kind_co' (go_co subst' co) go_co subst (FunCo r afl afr w co1 co2) = mkFunCo2 r afl afr (go_co subst w) (go_co subst co1) (go_co subst co2) go_co subst (CoVarCo cv) @@ -850,7 +851,7 @@ on all variables and binding sites. Primarily used for zonking. Note [Efficiency for ForAllCo case of mapTyCoX] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -As noted in Note [Forall coercions] in GHC.Core.TyCo.Rep, a ForAllCo is a bit redundant. +As noted in Note [ForAllCo] in GHC.Core.TyCo.Rep, a ForAllCo is a bit redundant. It stores a TyCoVar and a Coercion, where the kind of the TyCoVar always matches the left-hand kind of the coercion. This is convenient lots of the time, but not when mapping a function over a coercion. @@ -991,11 +992,12 @@ mapTyCoX (TyCoMapper { tcm_tyvar = tyvar | otherwise = mkTyConAppCo r tc <$> go_cos env cos - go_co !env (ForAllCo tv kind_co co) + go_co !env (ForAllCo { fco_tcv = tv, fco_visL = visL, fco_visR = visR + , fco_kind = kind_co, fco_body = co }) = do { kind_co' <- go_co env kind_co - ; tycobinder env tv Inferred $ \env' tv' -> do + ; tycobinder env tv visL $ \env' tv' -> do ; co' <- go_co env' co - ; return $ mkForAllCo tv' kind_co' co' } + ; return $ mkForAllCo tv' visL visR kind_co' co' } -- See Note [Efficiency for ForAllCo case of mapTyCoX] go_prov !env (PhantomProv co) = PhantomProv <$> go_co env co @@ -1063,14 +1065,13 @@ The type (Proxy (Eq Int => Int)) is only accepted with -XImpredicativeTypes, but suppose we want that. But then in the call to 'i', we end up decomposing (Eq Int => Int), and we definitely don't want that. -This really only applies to the type checker; in Core, '=>' and '->' -are the same, as are 'Constraint' and '*'. But for now I've put -the test in splitAppTyNoView_maybe, which applies throughout, because -the other calls to splitAppTy are in GHC.Core.Unify, which is also used by -the type checker (e.g. when matching type-function equations). - We are willing to split (t1 -=> t2) because the argument is still of kind Type, not Constraint. So the criterion is isVisibleFunArg. + +In Core there is no real reason to avoid such decomposition. But for now I've +put the test in splitAppTyNoView_maybe, which applies throughout, because the +other calls to splitAppTy are in GHC.Core.Unify, which is also used by the +type checker (e.g. when matching type-function equations). -} -- | Applies a type to another, as in e.g. @k a@ @@ -1763,14 +1764,25 @@ tyConBindersPiTyBinders = map to_tyb to_tyb (Bndr tv (NamedTCB vis)) = Named (Bndr tv vis) to_tyb (Bndr tv AnonTCB) = Anon (tymult (varType tv)) FTF_T_T --- | Make a dependent forall over an 'Inferred' variable -mkTyCoInvForAllTy :: TyCoVar -> Type -> Type -mkTyCoInvForAllTy tv ty +-- | Make a dependent forall over a TyCoVar +mkTyCoForAllTy :: TyCoVar -> ForAllTyFlag -> Type -> Type +mkTyCoForAllTy tv vis ty | isCoVar tv , not (tv `elemVarSet` tyCoVarsOfType ty) + -- Maintain ForAllTy's invariants + -- See Note [Unused coercion variable in ForAllTy] in GHC.Core.TyCo.Rep = mkVisFunTyMany (varType tv) ty | otherwise - = ForAllTy (Bndr tv Inferred) ty + = ForAllTy (mkForAllTyBinder vis tv) ty + +-- | Make a dependent forall over a TyCoVar +mkTyCoForAllTys :: [ForAllTyBinder] -> Type -> Type +mkTyCoForAllTys bndrs ty + = foldr (\(Bndr var vis) -> mkTyCoForAllTy var vis) ty bndrs + +-- | Make a dependent forall over an 'Inferred' variable +mkTyCoInvForAllTy :: TyCoVar -> Type -> Type +mkTyCoInvForAllTy tv ty = mkTyCoForAllTy tv Inferred ty -- | Like 'mkTyCoInvForAllTy', but tv should be a tyvar mkInfForAllTy :: TyVar -> Type -> Type @@ -1937,14 +1949,20 @@ dropForAlls ty = go ty go ty | Just ty' <- coreView ty = go ty' go res = res --- | Attempts to take a forall type apart, but only if it's a proper forall, --- with a named binder +-- | Attempts to take a ForAllTy apart, returning the full ForAllTyBinder +splitForAllForAllTyBinder_maybe :: Type -> Maybe (ForAllTyBinder, Type) +splitForAllForAllTyBinder_maybe ty + | ForAllTy bndr inner_ty <- coreFullView ty = Just (bndr, inner_ty) + | otherwise = Nothing + + +-- | Attempts to take a ForAllTy apart, returning the Var splitForAllTyCoVar_maybe :: Type -> Maybe (TyCoVar, Type) splitForAllTyCoVar_maybe ty | ForAllTy (Bndr tv _) inner_ty <- coreFullView ty = Just (tv, inner_ty) | otherwise = Nothing --- | Like 'splitForAllTyCoVar_maybe', but only returns Just if it is a tyvar binder. +-- | Attempts to take a ForAllTy apart, but only if the binder is a TyVar splitForAllTyVar_maybe :: Type -> Maybe (TyVar, Type) splitForAllTyVar_maybe ty | ForAllTy (Bndr tv _) inner_ty <- coreFullView ty diff --git a/compiler/GHC/Core/Unify.hs b/compiler/GHC/Core/Unify.hs index eefb9e35ac174ebf83e7aa9dfdb8b39cce7aa96f..e268bee26aed5a3babfcfe9cea2eb665e3c9b8c6 100644 --- a/compiler/GHC/Core/Unify.hs +++ b/compiler/GHC/Core/Unify.hs @@ -1675,10 +1675,14 @@ ty_co_match menv subst (FunTy { ft_mult = w, ft_arg = ty1, ft_res = ty2 }) -- NB: we include the RuntimeRep arguments in the matching; -- not doing so caused #21205. -ty_co_match menv subst (ForAllTy (Bndr tv1 _) ty1) - (ForAllCo tv2 kind_co2 co2) +ty_co_match menv subst (ForAllTy (Bndr tv1 vis1t) ty1) + (ForAllCo tv2 vis1c vis2c kind_co2 co2) lkco rkco | isTyVar tv1 && isTyVar tv2 + , vis1t == vis1c && vis1c == vis2c -- Is this necessary? + -- Is this visibility check necessary? @rae says: yes, I think the + -- check is necessary, if we're caring about visibility (and we are). + -- But ty_co_match is a dark and not important corner. = do { subst1 <- ty_co_match menv subst (tyVarKind tv1) kind_co2 ki_ki_co ki_ki_co ; let rn_env0 = me_env menv @@ -1778,9 +1782,10 @@ pushRefl co = -> Just (FunCo r af af (mkReflCo r w) (mkReflCo r ty1) (mkReflCo r ty2)) Just (TyConApp tc tys, r) -> Just (TyConAppCo r tc (zipWith mkReflCo (tyConRoleListX r tc) tys)) - Just (ForAllTy (Bndr tv _) ty, r) - -> Just (ForAllCo tv (mkNomReflCo (varType tv)) (mkReflCo r ty)) - -- NB: NoRefl variant. Otherwise, we get a loop! + Just (ForAllTy (Bndr tv vis) ty, r) + -> Just (ForAllCo { fco_tcv = tv, fco_visL = vis, fco_visR = vis + , fco_kind = mkNomReflCo (varType tv) + , fco_body = mkReflCo r ty }) _ -> Nothing {- diff --git a/compiler/GHC/Core/Utils.hs b/compiler/GHC/Core/Utils.hs index efd74a3a67159d55ee176ca05fa80e38c6b11d55..89439af515139da9d5a26a12782d80e03a21eb18 100644 --- a/compiler/GHC/Core/Utils.hs +++ b/compiler/GHC/Core/Utils.hs @@ -21,7 +21,8 @@ module GHC.Core.Utils ( scaleAltsBy, -- * Properties of expressions - exprType, coreAltType, coreAltsType, mkLamType, mkLamTypes, + exprType, coreAltType, coreAltsType, + mkLamType, mkLamTypes, mkFunctionType, exprIsDupable, exprIsTrivial, getIdFromTrivialExpr, getIdFromTrivialExpr_maybe, @@ -161,17 +162,20 @@ mkLamType :: HasDebugCallStack => Var -> Type -> Type -- ^ Makes a @(->)@ type or an implicit forall type, depending -- on whether it is given a type variable or a term variable. -- This is used, for example, when producing the type of a lambda. --- Always uses Inferred binders. +-- mkLamTypes :: [Var] -> Type -> Type -- ^ 'mkLamType' for multiple type or value arguments mkLamType v body_ty | isTyVar v - = mkForAllTy (Bndr v Inferred) body_ty + = mkForAllTy (Bndr v coreTyLamForAllTyFlag) body_ty + -- coreTyLamForAllTyFlag: see (FC4) in Note [ForAllCo] + -- in GHC.Core.TyCo.Rep | isCoVar v , v `elemVarSet` tyCoVarsOfType body_ty - = mkForAllTy (Bndr v Required) body_ty + -- See Note [Unused coercion variable in ForAllTy] in GHC.Core.TyCo.Rep + = mkForAllTy (Bndr v coreTyLamForAllTyFlag) body_ty | otherwise = mkFunctionType (varMult v) (varType v) body_ty diff --git a/compiler/GHC/CoreToIface.hs b/compiler/GHC/CoreToIface.hs index c0b66e204913b64c20bc658e09e539bf01df9c77..16707c92a0c6c22d1bae0ed8213a121fdff667d5 100644 --- a/compiler/GHC/CoreToIface.hs +++ b/compiler/GHC/CoreToIface.hs @@ -309,9 +309,12 @@ toIfaceCoercionX fr co go (FunCo { fco_role = r, fco_mult = w, fco_arg = co1, fco_res = co2 }) = IfaceFunCo r (go w) (go co1) (go co2) - go (ForAllCo tv k co) = IfaceForAllCo (toIfaceBndr tv) - (toIfaceCoercionX fr' k) - (toIfaceCoercionX fr' co) + go (ForAllCo tv visL visR k co) + = IfaceForAllCo (toIfaceBndr tv) + visL + visR + (toIfaceCoercionX fr' k) + (toIfaceCoercionX fr' co) where fr' = fr `delVarSet` tv diff --git a/compiler/GHC/Iface/Rename.hs b/compiler/GHC/Iface/Rename.hs index b372e7a1d91ad0313c87d74edcad74088b7b1d5a..fe08cad0599cd8dd3b7433caa2c91ac769b2d7b8 100644 --- a/compiler/GHC/Iface/Rename.hs +++ b/compiler/GHC/Iface/Rename.hs @@ -668,8 +668,9 @@ rnIfaceCo (IfaceTyConAppCo role tc cos) = IfaceTyConAppCo role <$> rnIfaceTyCon tc <*> mapM rnIfaceCo cos rnIfaceCo (IfaceAppCo co1 co2) = IfaceAppCo <$> rnIfaceCo co1 <*> rnIfaceCo co2 -rnIfaceCo (IfaceForAllCo bndr co1 co2) - = IfaceForAllCo <$> rnIfaceBndr bndr <*> rnIfaceCo co1 <*> rnIfaceCo co2 +rnIfaceCo (IfaceForAllCo bndr visL visR co1 co2) + = (\bndr' co1' co2' -> IfaceForAllCo bndr' visL visR co1' co2') + <$> rnIfaceBndr bndr <*> rnIfaceCo co1 <*> rnIfaceCo co2 rnIfaceCo (IfaceFreeCoVar c) = pure (IfaceFreeCoVar c) rnIfaceCo (IfaceCoVarCo lcl) = IfaceCoVarCo <$> pure lcl rnIfaceCo (IfaceHoleCo lcl) = IfaceHoleCo <$> pure lcl diff --git a/compiler/GHC/Iface/Syntax.hs b/compiler/GHC/Iface/Syntax.hs index 289997f3aaf9b8b64beeabaad0a7ea9552bbc5ea..3a7795a92d3b6fa478ba5de5bb642a0e4fcf04f2 100644 --- a/compiler/GHC/Iface/Syntax.hs +++ b/compiler/GHC/Iface/Syntax.hs @@ -1766,7 +1766,7 @@ freeNamesIfCoercion (IfaceTyConAppCo _ tc cos) = freeNamesIfTc tc &&& fnList freeNamesIfCoercion cos freeNamesIfCoercion (IfaceAppCo c1 c2) = freeNamesIfCoercion c1 &&& freeNamesIfCoercion c2 -freeNamesIfCoercion (IfaceForAllCo _ kind_co co) +freeNamesIfCoercion (IfaceForAllCo _tcv _visL _visR kind_co co) = freeNamesIfCoercion kind_co &&& freeNamesIfCoercion co freeNamesIfCoercion (IfaceFreeCoVar _) = emptyNameSet freeNamesIfCoercion (IfaceCoVarCo _) = emptyNameSet diff --git a/compiler/GHC/Iface/Type.hs b/compiler/GHC/Iface/Type.hs index 6243e40470264218f4c6f924fde4470c5e01128f..1ea0307fc5346ec90db2218412e65e2766ea90ed 100644 --- a/compiler/GHC/Iface/Type.hs +++ b/compiler/GHC/Iface/Type.hs @@ -381,7 +381,7 @@ data IfaceCoercion | IfaceFunCo Role IfaceCoercion IfaceCoercion IfaceCoercion | IfaceTyConAppCo Role IfaceTyCon [IfaceCoercion] | IfaceAppCo IfaceCoercion IfaceCoercion - | IfaceForAllCo IfaceBndr IfaceCoercion IfaceCoercion + | IfaceForAllCo IfaceBndr !ForAllTyFlag !ForAllTyFlag IfaceCoercion IfaceCoercion | IfaceCoVarCo IfLclName | IfaceAxiomInstCo IfExtName BranchIndex [IfaceCoercion] | IfaceAxiomRuleCo IfLclName [IfaceCoercion] @@ -1282,7 +1282,8 @@ pprIfaceForAllPartMust :: [IfaceForAllBndr] -> [IfacePredType] -> SDoc -> SDoc pprIfaceForAllPartMust tvs ctxt sdoc = ppr_iface_forall_part ShowForAllMust tvs ctxt sdoc -pprIfaceForAllCoPart :: [(IfLclName, IfaceCoercion)] -> SDoc -> SDoc +pprIfaceForAllCoPart :: [(IfLclName, IfaceCoercion, ForAllTyFlag, ForAllTyFlag)] + -> SDoc -> SDoc pprIfaceForAllCoPart tvs sdoc = sep [ pprIfaceForAllCo tvs, sdoc ] @@ -1321,11 +1322,11 @@ ppr_itv_bndrs all_bndrs@(bndr@(Bndr _ vis) : bndrs) vis1 | otherwise = (all_bndrs, []) ppr_itv_bndrs [] _ = ([], []) -pprIfaceForAllCo :: [(IfLclName, IfaceCoercion)] -> SDoc +pprIfaceForAllCo :: [(IfLclName, IfaceCoercion, ForAllTyFlag, ForAllTyFlag)] -> SDoc pprIfaceForAllCo [] = empty pprIfaceForAllCo tvs = text "forall" <+> pprIfaceForAllCoBndrs tvs <> dot -pprIfaceForAllCoBndrs :: [(IfLclName, IfaceCoercion)] -> SDoc +pprIfaceForAllCoBndrs :: [(IfLclName, IfaceCoercion, ForAllTyFlag, ForAllTyFlag)] -> SDoc pprIfaceForAllCoBndrs bndrs = hsep $ map pprIfaceForAllCoBndr bndrs pprIfaceForAllBndr :: IfaceForAllBndr -> SDoc @@ -1340,9 +1341,15 @@ pprIfaceForAllBndr bndr = -- See Note [Suppressing binder signatures] suppress_sig = SuppressBndrSig False -pprIfaceForAllCoBndr :: (IfLclName, IfaceCoercion) -> SDoc -pprIfaceForAllCoBndr (tv, kind_co) - = parens (ppr tv <+> dcolon <+> pprIfaceCoercion kind_co) +pprIfaceForAllCoBndr :: (IfLclName, IfaceCoercion, ForAllTyFlag, ForAllTyFlag) -> SDoc +pprIfaceForAllCoBndr (tv, kind_co, visL, visR) + = parens (ppr tv <> pp_vis <+> dcolon <+> pprIfaceCoercion kind_co) + where + pp_vis | visL == coreTyLamForAllTyFlag + , visR == coreTyLamForAllTyFlag + = empty + | otherwise + = ppr visL <> char '~' <> ppr visR -- "[spec]~[reqd]" -- | Show forall flag -- @@ -1850,14 +1857,15 @@ ppr_co ctxt_prec (IfaceAppCo co1 co2) ppr_co funPrec co1 <+> pprParendIfaceCoercion co2 ppr_co ctxt_prec co@(IfaceForAllCo {}) = maybeParen ctxt_prec funPrec $ + -- FIXME: collect and pretty-print visibility info? pprIfaceForAllCoPart tvs (pprIfaceCoercion inner_co) where (tvs, inner_co) = split_co co - split_co (IfaceForAllCo (IfaceTvBndr (name, _)) kind_co co') - = let (tvs, co'') = split_co co' in ((name,kind_co):tvs,co'') - split_co (IfaceForAllCo (IfaceIdBndr (_, name, _)) kind_co co') - = let (tvs, co'') = split_co co' in ((name,kind_co):tvs,co'') + split_co (IfaceForAllCo (IfaceTvBndr (name, _)) visL visR kind_co co') + = let (tvs, co'') = split_co co' in ((name,kind_co,visL,visR):tvs,co'') + split_co (IfaceForAllCo (IfaceIdBndr (_, name, _)) visL visR kind_co co') + = let (tvs, co'') = split_co co' in ((name,kind_co,visL,visR):tvs,co'') split_co co' = ([], co') -- Why these three? See Note [Free tyvars in IfaceType] @@ -2163,9 +2171,11 @@ instance Binary IfaceCoercion where putByte bh 5 put_ bh a put_ bh b - put_ bh (IfaceForAllCo a b c) = do + put_ bh (IfaceForAllCo a visL visR b c) = do putByte bh 6 put_ bh a + put_ bh visL + put_ bh visR put_ bh b put_ bh c put_ bh (IfaceCoVarCo a) = do @@ -2239,9 +2249,11 @@ instance Binary IfaceCoercion where b <- get bh return $ IfaceAppCo a b 6 -> do a <- get bh + visL <- get bh + visR <- get bh b <- get bh c <- get bh - return $ IfaceForAllCo a b c + return $ IfaceForAllCo a visL visR b c 7 -> do a <- get bh return $ IfaceCoVarCo a 8 -> do a <- get bh @@ -2339,7 +2351,7 @@ instance NFData IfaceCoercion where IfaceFunCo f1 f2 f3 f4 -> f1 `seq` rnf f2 `seq` rnf f3 `seq` rnf f4 IfaceTyConAppCo f1 f2 f3 -> f1 `seq` rnf f2 `seq` rnf f3 IfaceAppCo f1 f2 -> rnf f1 `seq` rnf f2 - IfaceForAllCo f1 f2 f3 -> rnf f1 `seq` rnf f2 `seq` rnf f3 + IfaceForAllCo f1 f2 f3 f4 f5 -> rnf f1 `seq` rnf f2 `seq` rnf f3 `seq` rnf f4 `seq` rnf f5 IfaceCoVarCo f1 -> rnf f1 IfaceAxiomInstCo f1 f2 f3 -> rnf f1 `seq` rnf f2 `seq` rnf f3 IfaceAxiomRuleCo f1 f2 -> rnf f1 `seq` rnf f2 diff --git a/compiler/GHC/IfaceToCore.hs b/compiler/GHC/IfaceToCore.hs index 814fce49badc5cb73502c29781710cf119f11b3a..1d6c49b6b2a18ee13228ba211bfb9736718fc39a 100644 --- a/compiler/GHC/IfaceToCore.hs +++ b/compiler/GHC/IfaceToCore.hs @@ -1463,9 +1463,9 @@ tcIfaceCo = go go (IfaceFunCo r w c1 c2) = mkFunCoNoFTF r <$> go w <*> go c1 <*> go c2 go (IfaceTyConAppCo r tc cs) = TyConAppCo r <$> tcIfaceTyCon tc <*> mapM go cs go (IfaceAppCo c1 c2) = AppCo <$> go c1 <*> go c2 - go (IfaceForAllCo tv k c) = do { k' <- go k + go (IfaceForAllCo tv visL visR k c) = do { k' <- go k ; bindIfaceBndr tv $ \ tv' -> - ForAllCo tv' k' <$> go c } + ForAllCo tv' visL visR k' <$> go c } go (IfaceCoVarCo n) = CoVarCo <$> go_var n go (IfaceAxiomInstCo n i cs) = AxiomInstCo <$> tcIfaceCoAxiom n <*> pure i <*> mapM go cs go (IfaceUnivCo p r t1 t2) = UnivCo <$> tcIfaceUnivCoProv p <*> pure r diff --git a/compiler/GHC/Tc/Solver/Equality.hs b/compiler/GHC/Tc/Solver/Equality.hs index 0dc574723279862183cb237343f853b1d437df16..c8bb3a5eeb85bbbabfc1e5623f27403a7fa32bd2 100644 --- a/compiler/GHC/Tc/Solver/Equality.hs +++ b/compiler/GHC/Tc/Solver/Equality.hs @@ -21,6 +21,7 @@ import GHC.Tc.Utils.Unify import GHC.Tc.Utils.TcType import GHC.Tc.Instance.Family ( tcTopNormaliseNewTypeTF_maybe ) import GHC.Tc.Instance.FunDeps( FunDepEqn(..) ) +import qualified GHC.Tc.Utils.Monad as TcM import GHC.Core.Type import GHC.Core.Predicate @@ -467,29 +468,24 @@ Missing this point is what caused #15431 can_eq_nc_forall :: CtEvidence -> EqRel -> Type -> Type -- LHS and RHS -> TcS (StopOrContinue (Either IrredCt EqCt)) --- (forall as. phi1) ~ (forall bs. phi2) --- Check for length match of as, bs --- Then build an implication constraint: forall as. phi1 ~ phi2[as/bs] --- But remember also to unify the kinds of as and bs --- (this is the 'go' loop), and actually substitute phi2[as |> cos / bs] --- Remember also that we might have forall z (a:z). blah --- so we must proceed one binder at a time (#13879) +-- See Note [Solving forall equalities] can_eq_nc_forall ev eq_rel s1 s2 - | CtWanted { ctev_loc = loc, ctev_dest = orig_dest, ctev_rewriters = rewriters } <- ev - = do { let free_tvs = tyCoVarsOfTypes [s1,s2] - (bndrs1, phi1) = tcSplitForAllTyVarBinders s1 - (bndrs2, phi2) = tcSplitForAllTyVarBinders s2 + | CtWanted { ctev_dest = orig_dest } <- ev + = do { let (bndrs1, phi1, bndrs2, phi2) = split_foralls s1 s2 flags1 = binderFlags bndrs1 flags2 = binderFlags bndrs2 - ; if not (all2 eqForAllVis flags1 flags2) -- Note [ForAllTy and type equality] - then do { traceTcS "Forall failure" $ + + ; if eq_rel == NomEq && not (all2 eqForAllVis flags1 flags2) -- Note [ForAllTy and type equality] + then do { traceTcS "Forall failure: visibility-mismatch" $ vcat [ ppr s1, ppr s2, ppr bndrs1, ppr bndrs2 , ppr flags1, ppr flags2 ] ; canEqHardFailure ev s1 s2 } - else - do { traceTcS "Creating implication for polytype equality" $ ppr ev - ; let empty_subst1 = mkEmptySubst $ mkInScopeSet free_tvs + + else do { + traceTcS "Creating implication for polytype equality" (ppr ev) + ; let free_tvs = tyCoVarsOfTypes [s1,s2] + empty_subst1 = mkEmptySubst $ mkInScopeSet free_tvs ; skol_info <- mkSkolemInfo (UnifyForAllSkol phi1) ; (subst1, skol_tvs) <- tcInstSkolTyVarsX skol_info empty_subst1 $ binderVars bndrs1 @@ -497,31 +493,44 @@ can_eq_nc_forall ev eq_rel s1 s2 ; let phi1' = substTy subst1 phi1 -- Unify the kinds, extend the substitution - go :: [TcTyVar] -> Subst -> [TyVarBinder] - -> TcS (TcCoercion, Cts) - go (skol_tv:skol_tvs) subst (bndr2:bndrs2) - = do { let tv2 = binderVar bndr2 - ; (kind_co, wanteds1) <- unify loc rewriters Nominal (tyVarKind skol_tv) - (substTy subst (tyVarKind tv2)) - ; let subst' = extendTvSubstAndInScope subst tv2 + go :: UnifyEnv -> [TcTyVar] -> Subst + -> [TyVarBinder] -> [TyVarBinder] -> TcM.TcM TcCoercion + go uenv (skol_tv:skol_tvs) subst2 (bndr1:bndrs1) (bndr2:bndrs2) + = do { let tv2 = binderVar bndr2 + vis1 = binderFlag bndr1 + vis2 = binderFlag bndr2 + + -- Unify the kinds, at Nominal role + -- See (SF1) in Note [Solving forall equalities] + ; kind_co <- uType (uenv `setUEnvRole` Nominal) + (tyVarKind skol_tv) + (substTy subst2 (tyVarKind tv2)) + + ; let subst2' = extendTvSubstAndInScope subst2 tv2 (mkCastTy (mkTyVarTy skol_tv) kind_co) -- skol_tv is already in the in-scope set, but the -- free vars of kind_co are not; hence "...AndInScope" - ; (co, wanteds2) <- go skol_tvs subst' bndrs2 - ; return ( mkForAllCo skol_tv kind_co co - , wanteds1 `unionBags` wanteds2 ) } + ; co <- go uenv skol_tvs subst2' bndrs1 bndrs2 + + ; return (mkNakedForAllCo skol_tv vis1 vis2 kind_co co)} + -- mkNaked.. because these types are not zonked, and the + -- assertions in mkForAllCo may fail without that zonking -- Done: unify phi1 ~ phi2 - go [] subst bndrs2 - = assert (null bndrs2) $ - unify loc rewriters (eqRelRole eq_rel) phi1' (substTyUnchecked subst phi2) + go uenv [] subst2 bndrs1 bndrs2 + = assert (null bndrs1 && null bndrs2) $ + uType uenv phi1' (substTyUnchecked subst2 phi2) - go _ _ _ = panic "cna_eq_nc_forall" -- case (s:ss) [] + go _ _ _ _ _ = panic "can_eq_nc_forall" -- case (s:ss) [] - empty_subst2 = mkEmptySubst (getSubstInScope subst1) + init_subst2 = mkEmptySubst (getSubstInScope subst1) + + -- Generate the constraints that live in the body of the implication + -- See (SF5) in Note [Solving forall equalities] + ; (lvl, (all_co, wanteds)) <- pushLevelNoWorkList (ppr skol_info) $ + unifyForAllBody ev (eqRelRole eq_rel) $ \uenv -> + go uenv skol_tvs init_subst2 bndrs1 bndrs2 - ; (lvl, (all_co, wanteds)) <- pushLevelNoWorkList (ppr skol_info) $ - go skol_tvs empty_subst2 bndrs2 ; emitTvImplicationTcS lvl (getSkolemInfo skol_info) skol_tvs wanteds ; setWantedEq orig_dest all_co @@ -533,16 +542,69 @@ can_eq_nc_forall ev eq_rel s1 s2 ; stopWith ev "Discard given polytype equality" } where - unify :: CtLoc -> RewriterSet -> Role -> TcType -> TcType -> TcS (TcCoercion, Cts) - -- This version returns the wanted constraint rather - -- than putting it in the work list - unify loc rewriters role ty1 ty2 - | ty1 `tcEqType` ty2 - = return (mkReflCo role ty1, emptyBag) - | otherwise - = do { (wanted, co) <- newWantedEq loc rewriters role ty1 ty2 - ; return (co, unitBag (mkNonCanonical wanted)) } - + split_foralls :: TcType -> TcType + -> ( [ForAllTyBinder], TcType + , [ForAllTyBinder], TcType) + -- Split matching foralls; stop when the foralls don't match + -- See #22537. See (SF3) in Note [Solving forall equalities] + -- Postcondition: the two lists of binders returned have the same length + split_foralls s1 s2 + | Just (bndr1, s1') <- splitForAllForAllTyBinder_maybe s1 + , Just (bndr2, s2') <- splitForAllForAllTyBinder_maybe s2 + = let !(bndrs1, phi1, bndrs2, phi2) = split_foralls s1' s2' + in (bndr1:bndrs1, phi1, bndr2:bndrs2, phi2) + split_foralls s1 s2 = ([], s1, [], s2) + +{- Note [Solving forall equalities] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To solve an equality between foralls + [W] (forall a. t1) ~ (forall b. t2) +the basic plan is simple: just create the implication constraint + [W] forall a. { t1 ~ (t2[a/b]) } + +The evidence we produce is a ForAllCo; see the typing rule for +ForAllCo in Note [ForAllCo] in GHC.Tc.TyCo.Rep. + +There are lots of wrinkles of course: + +(SF1) We must check the kinds match (at Nominal role). So from + [W] (forall (a:ka). t1) ~ (forall (b:kb). t2) + we actually generate the implication + [W] forall (a:ka). { ka ~N kb, t1 ~ t2[a/b] } + These kind equalities are generated by the `go` loop in `can_eq_nc_forall`. + Why Nominal role? See the typing rule for ForAllCo. + +(SF2) At Nominal role we must check that the visiblities match. + For example + [W] (forall a. a -> a) ~N (forall b -> b -> b) + should fail. At /Representational/ role we allow this; see the + typing rule for ForAllCo, mentioned above. + +(SF3) Consider this (#22537) + newtype P a = MkP (forall c. (a,c)) + [W] (forall a. P a) ~R (forall a b. (a,b)) + The number of foralls does not line up. But if we just unwrap the outer + forall a, we'll get + [W] P a ~R forall b. (a,b) + Now unwrap the newtype + [W] (forall c. (a,c)) ~R (forall b. (a,b)) + and all is good. + + Conclusion: Don't fail if the number of foralls does not line up. Instead, + handle as many binders as are visibly apparent on both sides, and then keep + going with unification. See `split_foralls` in `can_eq_nc_forall`. In the + above example, at Representational role, the unifier will proceed to unwrap + the newtype on the RHS and we'll end up back in can_eq_nc_forall. + +(SF4) Remember also that we might have forall z (a:z). blah + so in that `go` loop, we must proceed one binder at a time (#13879) + +(SF5) Rather than manually gather the constraints needed in the body of the + implication, we use `uType`. That way we can solve some of them on the fly, + especially Refl ones. We use the `unifyForAllBody` wrapper for `uType`, + because we want to /gather/ the equality constraint (to put in the implication) + rather than /emit/ them into the monad, as `wrapUnifierTcS` does. +-} {- Note [Unwrap newtypes first] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -3188,4 +3250,4 @@ To avoid this situation we do not cache as solved any workitems (or inert) which did not really made a 'step' towards proving some goal. Solved's are just an optimization so we don't lose anything in terms of completeness of solving. --} \ No newline at end of file +-} diff --git a/compiler/GHC/Tc/Solver/Monad.hs b/compiler/GHC/Tc/Solver/Monad.hs index da38736dbfc7982c7307c63acb09ebdf7c91bd4b..9943ae543597fc90b9e54f7c819b605410c36aca 100644 --- a/compiler/GHC/Tc/Solver/Monad.hs +++ b/compiler/GHC/Tc/Solver/Monad.hs @@ -97,7 +97,7 @@ module GHC.Tc.Solver.Monad ( instDFunType, -- Unification - wrapUnifierTcS, unifyFunDeps, uPairsTcM, + wrapUnifierTcS, unifyFunDeps, uPairsTcM, unifyForAllBody, -- MetaTyVars newFlexiTcSTy, instFlexiX, @@ -1998,6 +1998,22 @@ unifyFunDeps ev role do_unifications where fvs = tyCoVarsOfType (ctEvPred ev) +unifyForAllBody :: CtEvidence -> Role -> (UnifyEnv -> TcM a) + -> TcS (a, Cts) +-- We /return/ the equality constraints we generate, +-- rather than emitting them into the monad. +-- See See (SF5) in Note [Solving forall equalities] in GHC.Tc.Solver.Equality +unifyForAllBody ev role unify_body + = do { (res, cts, unified, _rewriters) <- wrapUnifierX ev role unify_body + -- Ignore the rewriters. They are used in wrapUnifierTcS only + -- as an optimistion to prioritise the work list; but they are + -- /also/ stored in each individual constraint we return. + + -- Kick out any inert constraint that we have unified + ; _ <- kickOutAfterUnification unified + + ; return (res, cts) } + wrapUnifierTcS :: CtEvidence -> Role -> (UnifyEnv -> TcM a) -- Some calls to uType -> TcS (a, Bag Ct, [TcTyVar]) @@ -2011,31 +2027,41 @@ wrapUnifierTcS :: CtEvidence -> Role -- unified the process; the (Bag Ct) are the deferred constraints. wrapUnifierTcS ev role do_unifications - = do { (cos, unified, rewriters, cts) <- wrapTcS $ - do { defer_ref <- TcM.newTcRef emptyBag - ; unified_ref <- TcM.newTcRef [] - ; rewriters <- TcM.zonkRewriterSet (ctEvRewriters ev) - ; let env = UE { u_role = role - , u_rewriters = rewriters - , u_loc = ctEvLoc ev - , u_defer = defer_ref - , u_unified = Just unified_ref} - - ; cos <- do_unifications env - - ; cts <- TcM.readTcRef defer_ref - ; unified <- TcM.readTcRef unified_ref - ; return (cos, unified, rewriters, cts) } + = do { (res, cts, unified, rewriters) <- wrapUnifierX ev role do_unifications -- Emit the deferred constraints -- See Note [Work-list ordering] in GHC.Tc.Solved.Equality + -- + -- All the constraints in `cts` share the same rewriter set so, + -- rather than looking at it one by one, we pass it to + -- extendWorkListEqs; just a small optimisation. ; unless (isEmptyBag cts) $ updWorkListTcS (extendWorkListEqs rewriters cts) -- And kick out any inert constraint that we have unified ; _ <- kickOutAfterUnification unified - ; return (cos, cts, unified) } + ; return (res, cts, unified) } + +wrapUnifierX :: CtEvidence -> Role + -> (UnifyEnv -> TcM a) -- Some calls to uType + -> TcS (a, Bag Ct, [TcTyVar], RewriterSet) +wrapUnifierX ev role do_unifications + = wrapTcS $ + do { defer_ref <- TcM.newTcRef emptyBag + ; unified_ref <- TcM.newTcRef [] + ; rewriters <- TcM.zonkRewriterSet (ctEvRewriters ev) + ; let env = UE { u_role = role + , u_rewriters = rewriters + , u_loc = ctEvLoc ev + , u_defer = defer_ref + , u_unified = Just unified_ref} + + ; res <- do_unifications env + + ; cts <- TcM.readTcRef defer_ref + ; unified <- TcM.readTcRef unified_ref + ; return (res, cts, unified, rewriters) } {- diff --git a/compiler/GHC/Tc/TyCl/Utils.hs b/compiler/GHC/Tc/TyCl/Utils.hs index dab5f3f77a03d76468f2f986815cd8d2405db605..9c9d356a22d2e059b0bd116c87ace777cd738824 100644 --- a/compiler/GHC/Tc/TyCl/Utils.hs +++ b/compiler/GHC/Tc/TyCl/Utils.hs @@ -139,7 +139,8 @@ synonymTyConsOfType ty go_co (GRefl _ ty mco) = go ty `plusNameEnv` go_mco mco go_co (TyConAppCo _ tc cs) = go_tc tc `plusNameEnv` go_co_s cs go_co (AppCo co co') = go_co co `plusNameEnv` go_co co' - go_co (ForAllCo _ co co') = go_co co `plusNameEnv` go_co co' + go_co (ForAllCo { fco_kind = kind_co, fco_body = body_co }) + = go_co kind_co `plusNameEnv` go_co body_co go_co (FunCo { fco_mult = m, fco_arg = a, fco_res = r }) = go_co m `plusNameEnv` go_co a `plusNameEnv` go_co r go_co (CoVarCo _) = emptyNameEnv diff --git a/compiler/GHC/Tc/Utils/TcMType.hs b/compiler/GHC/Tc/Utils/TcMType.hs index 748b18ab234e1ab494c532571060c6ce8849cf70..1e111fa83e567790c884d39d939fd28b6cca73d5 100644 --- a/compiler/GHC/Tc/Utils/TcMType.hs +++ b/compiler/GHC/Tc/Utils/TcMType.hs @@ -1447,7 +1447,7 @@ collect_cand_qtvs_co orig_ty cur_lvl bound = go_co go_co dv (CoVarCo cv) = go_cv dv cv - go_co dv (ForAllCo tcv kind_co co) + go_co dv (ForAllCo { fco_tcv = tcv, fco_kind = kind_co, fco_body = co }) = do { dv1 <- go_co dv kind_co ; collect_cand_qtvs_co orig_ty cur_lvl (bound `extendVarSet` tcv) dv1 co } diff --git a/compiler/GHC/Types/Var.hs b/compiler/GHC/Types/Var.hs index 0471688aa6771a5f51aad4c7e9b1dc71adc83391..bbc5454c9fc009396d8643bfb26acac080ee804f 100644 --- a/compiler/GHC/Types/Var.hs +++ b/compiler/GHC/Types/Var.hs @@ -69,6 +69,7 @@ module GHC.Types.Var ( ForAllTyFlag(Invisible,Required,Specified,Inferred), Specificity(..), isVisibleForAllTyFlag, isInvisibleForAllTyFlag, isInferredForAllTyFlag, + coreTyLamForAllTyFlag, -- * FunTyFlag FunTyFlag(..), isVisibleFunArg, isInvisibleFunArg, isFUNArg, @@ -126,6 +127,7 @@ import GHC.Utils.Panic import GHC.Utils.Panic.Plain import Data.Data +import Control.DeepSeq {- ************************************************************************ @@ -453,7 +455,7 @@ updateVarTypeM upd var -- permitted by request ('Specified') (visible type application), or -- prohibited entirely from appearing in source Haskell ('Inferred')? -- See Note [VarBndrs, ForAllTyBinders, TyConBinders, and visibility] in "GHC.Core.TyCo.Rep" -data ForAllTyFlag = Invisible Specificity +data ForAllTyFlag = Invisible !Specificity | Required deriving (Eq, Ord, Data) -- (<) on ForAllTyFlag means "is less visible than" @@ -487,6 +489,12 @@ isInferredForAllTyFlag :: ForAllTyFlag -> Bool isInferredForAllTyFlag (Invisible InferredSpec) = True isInferredForAllTyFlag _ = False +coreTyLamForAllTyFlag :: ForAllTyFlag +-- ^ The ForAllTyFlag on a (Lam a e) term, where `a` is a type variable. +-- If you want other ForAllTyFlag, use a cast. +-- See Note [ForAllCo] in GHC.Core.TyCo.Rep +coreTyLamForAllTyFlag = Specified + instance Outputable ForAllTyFlag where ppr Required = text "[req]" ppr Specified = text "[spec]" @@ -514,6 +522,13 @@ instance Binary ForAllTyFlag where 1 -> return Specified _ -> return Inferred +instance NFData Specificity where + rnf SpecifiedSpec = () + rnf InferredSpec = () +instance NFData ForAllTyFlag where + rnf (Invisible spec) = rnf spec + rnf Required = () + {- ********************************************************************* * * * FunTyFlag @@ -882,7 +897,7 @@ Wrinkles Note [VarBndrs, ForAllTyBinders, TyConBinders, and visibility] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * A ForAllTy (used for both types and kinds) contains a ForAllTyBinder. Each ForAllTyBinder Bndr a tvis diff --git a/docs/core-spec/core-spec.mng b/docs/core-spec/core-spec.mng index 1e77f3b4de95d470478b257414ca1bc4e2160fb2..95f79fbf7623cc5d5c0d792f6aa212e2a17f0b77 100644 --- a/docs/core-spec/core-spec.mng +++ b/docs/core-spec/core-spec.mng @@ -223,8 +223,8 @@ be a type function. the payload in a \texttt{Refl} must not be built with \texttt{CoercionTy}. \item If $[[forall z: h .g]]$ is a polymorphic coercion over a coercion variable (i.e. $[[z]]$ is a coercion variable), then $[[z]]$ can only appear in - \texttt{Refl} and \texttt{GRefl} in $[[g]]$. See \texttt{Note [Unused coercion - variable in ForAllCo] in \ghcfile{GHC.Core.Coercion}}. + \texttt{Refl} and \texttt{GRefl} in $[[g]]$. See \texttt{(FC6) in Note [ForAllCo] + in \ghcfile{GHC.Core.TyCon.Rep}}. \item Prefer $[[g1 ->_R g2]]$ over $[[(->)_R g1 g2]]$; that is, we use \ctor{FunCo}, never \ctor{TyConAppCo}, for coercions over saturated uses of $[[->]]$. \end{itemize} diff --git a/testsuite/tests/cpranal/should_compile/T18174.stderr b/testsuite/tests/cpranal/should_compile/T18174.stderr index b251d9914a48d657379b54bf2a8137ca72fcb024..b47152a95c68cdc723a207c045de2f676072996b 100644 --- a/testsuite/tests/cpranal/should_compile/T18174.stderr +++ b/testsuite/tests/cpranal/should_compile/T18174.stderr @@ -1,23 +1,18 @@ ==================== Tidy Core ==================== -Result size of Tidy Core = {terms: 464, types: 475, coercions: 6, joins: 0/3} +Result size of Tidy Core = {terms: 467, types: 458, coercions: 6, joins: 0/3} -- RHS size: {terms: 8, types: 7, coercions: 0, joins: 0/0} T18174.$WMkT :: Int %1 -> (Int, Int) %1 -> T -T18174.$WMkT = \ (conrep_aU0 :: Int) (conrep_aU1 :: (Int, Int)) -> case conrep_aU1 of conrep_X0 { __DEFAULT -> T18174.MkT conrep_aU0 conrep_X0 } +T18174.$WMkT = \ (conrep_aXh :: Int) (conrep1_aXi :: (Int, Int)) -> case conrep1_aXi of conrep2_aXi { __DEFAULT -> T18174.MkT conrep_aXh conrep2_aXi } --- RHS size: {terms: 5, types: 10, coercions: 0, joins: 0/0} +-- RHS size: {terms: 8, types: 15, coercions: 0, joins: 0/0} T18174.$wstrictField :: Int -> (Int, Int) -> (# Int, (Int, Int) #) -T18174.$wstrictField - = \ (ww_s18W :: Int) - (ww1_s18X - :: (Int, Int) - Unf=OtherCon []) -> - (# ww_s18W, ww1_s18X #) +T18174.$wstrictField = \ (ww_s1cs :: Int) (ww1_s1ct :: (Int, Int)) -> case ww1_s1ct of ww2_X1 { (ipv_s1ex, ipv1_s1ey) -> (# ww_s1cs, ww2_X1 #) } -- RHS size: {terms: 12, types: 21, coercions: 0, joins: 0/0} strictField :: T -> (Int, (Int, Int)) -strictField = \ (ds_s18U :: T) -> case ds_s18U of { MkT ww_s18W ww1_s18X -> case T18174.$wstrictField ww_s18W ww1_s18X of { (# ww2_s1aJ, ww3_s1aK #) -> (ww2_s1aJ, ww3_s1aK) } } +strictField = \ (ds_s1cq :: T) -> case ds_s1cq of { MkT ww_s1cs ww1_s1ct -> case T18174.$wstrictField ww_s1cs ww1_s1ct of { (# ww2_s1ef, ww3_s1eg #) -> (ww2_s1ef, ww3_s1eg) } } -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18174.$trModule4 :: GHC.Prim.Addr# @@ -40,20 +35,20 @@ T18174.$trModule :: GHC.Types.Module T18174.$trModule = GHC.Types.Module T18174.$trModule3 T18174.$trModule1 -- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} -$krep_r1c2 :: GHC.Types.KindRep -$krep_r1c2 = GHC.Types.KindRepTyConApp GHC.Types.$tcInt (GHC.Types.[] @GHC.Types.KindRep) +$krep_r1fR :: GHC.Types.KindRep +$krep_r1fR = GHC.Types.KindRepTyConApp GHC.Types.$tcInt (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0} -$krep1_r1c3 :: [GHC.Types.KindRep] -$krep1_r1c3 = GHC.Types.: @GHC.Types.KindRep $krep_r1c2 (GHC.Types.[] @GHC.Types.KindRep) +$krep1_r1fS :: [GHC.Types.KindRep] +$krep1_r1fS = GHC.Types.: @GHC.Types.KindRep $krep_r1fR (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} -$krep2_r1c4 :: [GHC.Types.KindRep] -$krep2_r1c4 = GHC.Types.: @GHC.Types.KindRep $krep_r1c2 $krep1_r1c3 +$krep2_r1fT :: [GHC.Types.KindRep] +$krep2_r1fT = GHC.Types.: @GHC.Types.KindRep $krep_r1fR $krep1_r1fS -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep3_r1c5 :: GHC.Types.KindRep -$krep3_r1c5 = GHC.Types.KindRepTyConApp GHC.Tuple.$tc(,) $krep2_r1c4 +$krep3_r1fU :: GHC.Types.KindRep +$krep3_r1fU = GHC.Types.KindRepTyConApp GHC.Tuple.Prim.$tcTuple2 $krep2_r1fT -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18174.$tcT2 :: GHC.Prim.Addr# @@ -65,19 +60,19 @@ T18174.$tcT1 = GHC.Types.TrNameS T18174.$tcT2 -- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0} T18174.$tcT :: GHC.Types.TyCon -T18174.$tcT = GHC.Types.TyCon 10767449832801551323## 11558512111670031614## T18174.$trModule T18174.$tcT1 0# GHC.Types.krep$* +T18174.$tcT = GHC.Types.TyCon 10767449832801551323#Word64 11558512111670031614#Word64 T18174.$trModule T18174.$tcT1 0# GHC.Types.krep$* -- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} -$krep4_r1c6 :: GHC.Types.KindRep -$krep4_r1c6 = GHC.Types.KindRepTyConApp T18174.$tcT (GHC.Types.[] @GHC.Types.KindRep) +$krep4_r1fV :: GHC.Types.KindRep +$krep4_r1fV = GHC.Types.KindRepTyConApp T18174.$tcT (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep5_r1c7 :: GHC.Types.KindRep -$krep5_r1c7 = GHC.Types.KindRepFun $krep3_r1c5 $krep4_r1c6 +$krep5_r1fW :: GHC.Types.KindRep +$krep5_r1fW = GHC.Types.KindRepFun $krep3_r1fU $krep4_r1fV -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} T18174.$tc'MkT1 :: GHC.Types.KindRep -T18174.$tc'MkT1 = GHC.Types.KindRepFun $krep_r1c2 $krep5_r1c7 +T18174.$tc'MkT1 = GHC.Types.KindRepFun $krep_r1fR $krep5_r1fW -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18174.$tc'MkT3 :: GHC.Prim.Addr# @@ -89,60 +84,60 @@ T18174.$tc'MkT2 = GHC.Types.TrNameS T18174.$tc'MkT3 -- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0} T18174.$tc'MkT :: GHC.Types.TyCon -T18174.$tc'MkT = GHC.Types.TyCon 15126196523434762667## 13148007393547580468## T18174.$trModule T18174.$tc'MkT2 0# T18174.$tc'MkT1 +T18174.$tc'MkT = GHC.Types.TyCon 15126196523434762667#Word64 13148007393547580468#Word64 T18174.$trModule T18174.$tc'MkT2 0# T18174.$tc'MkT1 -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} -lvl_r1c8 :: Int -lvl_r1c8 = GHC.Types.I# 1# +lvl_r1fX :: Int +lvl_r1fX = GHC.Types.I# 1# Rec { --- RHS size: {terms: 38, types: 38, coercions: 0, joins: 0/1} -T18174.$wfac3 :: forall {a}. GHC.Prim.Int# -> a -> (# a, Int #) +-- RHS size: {terms: 38, types: 37, coercions: 0, joins: 0/1} +T18174.$wfac3 :: forall a. GHC.Prim.Int# -> a -> (# a, Int #) T18174.$wfac3 - = \ (@a_s196) (ww_s199 :: GHC.Prim.Int#) (s_s19b :: a_s196) -> - case GHC.Prim.<# ww_s199 2# of { + = \ (@a_s1cC) (ww_s1cF :: GHC.Prim.Int#) (s_s1cH :: a_s1cC) -> + case GHC.Prim.<# ww_s1cF 2# of { __DEFAULT -> let { - ds_s18k :: (a_s196, Int) - ds_s18k = case T18174.$wfac3 @a_s196 (GHC.Prim.-# ww_s199 1#) s_s19b of { (# ww1_s1aM, ww2_s1aN #) -> (ww1_s1aM, ww2_s1aN) } } in - (# case ds_s18k of { (s'_aYW, n'_aYX) -> s'_aYW }, case ds_s18k of { (s'_aYW, n'_aYX) -> case n'_aYX of { GHC.Types.I# ww1_s193 -> GHC.Types.I# (GHC.Prim.*# ww1_s193 ww1_s193) } } #); - 1# -> (# s_s19b, lvl_r1c8 #) + ds_s1bj :: (a_s1cC, Int) + ds_s1bj = case T18174.$wfac3 @a_s1cC (GHC.Prim.-# ww_s1cF 1#) s_s1cH of { (# ww1_s1ei, ww2_s1ej #) -> (ww1_s1ei, ww2_s1ej) } } in + (# case ds_s1bj of { (s'_a12d, n'_a12e) -> s'_a12d }, case ds_s1bj of { (s'_a12d, n'_a12e) -> case n'_a12e of { GHC.Types.I# ww1_s1cz -> GHC.Types.I# (GHC.Prim.*# ww1_s1cz ww1_s1cz) } } #); + 1# -> (# s_s1cH, lvl_r1fX #) } end Rec } --- RHS size: {terms: 14, types: 16, coercions: 0, joins: 0/0} +-- RHS size: {terms: 14, types: 15, coercions: 0, joins: 0/0} fac3 :: forall a. Int -> a -> (a, Int) -fac3 = \ (@a_s196) (n_s197 :: Int) (s_s19b :: a_s196) -> case n_s197 of { GHC.Types.I# ww_s199 -> case T18174.$wfac3 @a_s196 ww_s199 s_s19b of { (# ww1_s1aM, ww2_s1aN #) -> (ww1_s1aM, ww2_s1aN) } } +fac3 = \ (@a_s1cC) (n_s1cD :: Int) (s_s1cH :: a_s1cC) -> case n_s1cD of { GHC.Types.I# ww_s1cF -> case T18174.$wfac3 @a_s1cC ww_s1cF s_s1cH of { (# ww1_s1ei, ww2_s1ej #) -> (ww1_s1ei, ww2_s1ej) } } Rec { --- RHS size: {terms: 24, types: 21, coercions: 0, joins: 0/0} -T18174.$wfac2 :: forall {a}. GHC.Prim.Int# -> a -> (# a, Int #) +-- RHS size: {terms: 24, types: 20, coercions: 0, joins: 0/0} +T18174.$wfac2 :: forall a. GHC.Prim.Int# -> a -> (# a, Int #) T18174.$wfac2 - = \ (@a_s19g) (ww_s19j :: GHC.Prim.Int#) (s_s19l :: a_s19g) -> - case GHC.Prim.<# ww_s19j 2# of { - __DEFAULT -> case T18174.$wfac2 @a_s19g (GHC.Prim.-# ww_s19j 1#) s_s19l of { (# ww1_s1aP, ww2_s1aQ #) -> (# ww1_s1aP, GHC.Num.$fNumInt_$c* ww2_s1aQ ww2_s1aQ #) }; - 1# -> (# s_s19l, lvl_r1c8 #) + = \ (@a_s1cM) (ww_s1cP :: GHC.Prim.Int#) (s_s1cR :: a_s1cM) -> + case GHC.Prim.<# ww_s1cP 2# of { + __DEFAULT -> case T18174.$wfac2 @a_s1cM (GHC.Prim.-# ww_s1cP 1#) s_s1cR of { (# ww1_s1el, ww2_s1em #) -> (# ww1_s1el, GHC.Num.$fNumInt_$c* ww2_s1em ww2_s1em #) }; + 1# -> (# s_s1cR, lvl_r1fX #) } end Rec } --- RHS size: {terms: 14, types: 16, coercions: 0, joins: 0/0} +-- RHS size: {terms: 14, types: 15, coercions: 0, joins: 0/0} fac2 :: forall a. Int -> a -> (a, Int) -fac2 = \ (@a_s19g) (n_s19h :: Int) (s_s19l :: a_s19g) -> case n_s19h of { GHC.Types.I# ww_s19j -> case T18174.$wfac2 @a_s19g ww_s19j s_s19l of { (# ww1_s1aP, ww2_s1aQ #) -> (ww1_s1aP, ww2_s1aQ) } } +fac2 = \ (@a_s1cM) (n_s1cN :: Int) (s_s1cR :: a_s1cM) -> case n_s1cN of { GHC.Types.I# ww_s1cP -> case T18174.$wfac2 @a_s1cM ww_s1cP s_s1cR of { (# ww1_s1el, ww2_s1em #) -> (ww1_s1el, ww2_s1em) } } Rec { --- RHS size: {terms: 24, types: 21, coercions: 0, joins: 0/0} -T18174.$wfac1 :: forall {a}. GHC.Prim.Int# -> a -> (# a, GHC.Prim.Int# #) +-- RHS size: {terms: 24, types: 20, coercions: 0, joins: 0/0} +T18174.$wfac1 :: forall a. GHC.Prim.Int# -> a -> (# a, GHC.Prim.Int# #) T18174.$wfac1 - = \ (@a_s19q) (ww_s19t :: GHC.Prim.Int#) (s_s19v :: a_s19q) -> - case GHC.Prim.<# ww_s19t 2# of { - __DEFAULT -> case T18174.$wfac1 @a_s19q (GHC.Prim.-# ww_s19t 1#) s_s19v of { (# ww1_s19y, ww2_s1aS #) -> (# ww1_s19y, GHC.Prim.*# ww_s19t ww2_s1aS #) }; - 1# -> (# s_s19v, 1# #) + = \ (@a_s1cW) (ww_s1cZ :: GHC.Prim.Int#) (s_s1d1 :: a_s1cW) -> + case GHC.Prim.<# ww_s1cZ 2# of { + __DEFAULT -> case T18174.$wfac1 @a_s1cW (GHC.Prim.-# ww_s1cZ 1#) s_s1d1 of { (# ww1_s1d4, ww2_s1eo #) -> (# ww1_s1d4, GHC.Prim.*# ww_s1cZ ww2_s1eo #) }; + 1# -> (# s_s1d1, 1# #) } end Rec } --- RHS size: {terms: 15, types: 16, coercions: 0, joins: 0/0} +-- RHS size: {terms: 15, types: 15, coercions: 0, joins: 0/0} fac1 :: forall a. Int -> a -> (a, Int) -fac1 = \ (@a_s19q) (n_s19r :: Int) (s_s19v :: a_s19q) -> case n_s19r of { GHC.Types.I# ww_s19t -> case T18174.$wfac1 @a_s19q ww_s19t s_s19v of { (# ww1_s19y, ww2_s1aS #) -> (ww1_s19y, GHC.Types.I# ww2_s1aS) } } +fac1 = \ (@a_s1cW) (n_s1cX :: Int) (s_s1d1 :: a_s1cW) -> case n_s1cX of { GHC.Types.I# ww_s1cZ -> case T18174.$wfac1 @a_s1cW ww_s1cZ s_s1d1 of { (# ww1_s1d4, ww2_s1eo #) -> (ww1_s1d4, GHC.Types.I# ww2_s1eo) } } -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} T18174.h5 :: Int @@ -151,51 +146,51 @@ T18174.h5 = GHC.Types.I# 0# -- RHS size: {terms: 37, types: 15, coercions: 0, joins: 0/1} T18174.$wg2 :: GHC.Prim.Int# -> GHC.Prim.Int# -> (# GHC.Prim.Int#, Int #) T18174.$wg2 - = \ (ww_s19G :: GHC.Prim.Int#) (ww1_s19K :: GHC.Prim.Int#) -> - case ww1_s19K of ds_X2 { + = \ (ww_s1dc :: GHC.Prim.Int#) (ww1_s1dg :: GHC.Prim.Int#) -> + case ww1_s1dg of ds_X2 { __DEFAULT -> - (# GHC.Prim.*# 2# ww_s19G, + (# GHC.Prim.*# 2# ww_s1dc, case ds_X2 of wild_X3 { __DEFAULT -> let { - c1#_a17n :: GHC.Prim.Int# - c1#_a17n = GHC.Prim.andI# 1# (GHC.Prim.<# wild_X3 0#) } in - case GHC.Prim.quotInt# (GHC.Prim.-# 2# c1#_a17n) wild_X3 of wild1_a17o { __DEFAULT -> GHC.Types.I# (GHC.Prim.-# wild1_a17o c1#_a17n) }; + c1#_a1co :: GHC.Prim.Int# + c1#_a1co = GHC.Prim.andI# 1# (GHC.Prim.<# wild_X3 0#) } in + case GHC.Prim.-# (GHC.Prim.quotInt# (GHC.Prim.-# 2# c1#_a1co) wild_X3) c1#_a1co of ds2_a1aa { __DEFAULT -> GHC.Types.I# ds2_a1aa }; 0# -> GHC.Real.divZeroError @Int } #); - 1# -> (# GHC.Prim.+# 2# ww_s19G, T18174.h5 #) + 1# -> (# GHC.Prim.+# 2# ww_s1dc, T18174.h5 #) } -- RHS size: {terms: 30, types: 19, coercions: 0, joins: 0/0} T18174.$wh2 :: GHC.Prim.Int# -> Int T18174.$wh2 - = \ (ww_s19W :: GHC.Prim.Int#) -> - case ww_s19W of ds_X2 { + = \ (ww_s1ds :: GHC.Prim.Int#) -> + case ww_s1ds of ds_X2 { __DEFAULT -> case GHC.Prim.remInt# ds_X2 2# of { - __DEFAULT -> case T18174.$wg2 ds_X2 2# of { (# ww1_s1aU, ww2_s19Q #) -> ww2_s19Q }; - 0# -> case T18174.$wg2 2# ds_X2 of { (# ww1_s1aU, ww2_s19Q #) -> case ww2_s19Q of { GHC.Types.I# y_a17v -> GHC.Types.I# (GHC.Prim.+# ww1_s1aU y_a17v) } } + __DEFAULT -> case T18174.$wg2 ds_X2 2# of { (# ww1_s1eq, ww2_s1dl #) -> ww2_s1dl }; + 0# -> case T18174.$wg2 2# ds_X2 of { (# ww1_s1eq, ww2_s1dl #) -> case ww2_s1dl of { GHC.Types.I# y_a1ah -> GHC.Types.I# (GHC.Prim.+# ww1_s1eq y_a1ah) } } }; 1# -> T18174.h5 } -- RHS size: {terms: 6, types: 3, coercions: 0, joins: 0/0} h2 :: Int -> Int -h2 = \ (ds_s19U :: Int) -> case ds_s19U of { GHC.Types.I# ww_s19W -> T18174.$wh2 ww_s19W } +h2 = \ (ds_s1dq :: Int) -> case ds_s1dq of { GHC.Types.I# ww_s1ds -> T18174.$wh2 ww_s1ds } -- RHS size: {terms: 34, types: 14, coercions: 0, joins: 0/1} T18174.$wg1 :: GHC.Prim.Int# -> (# GHC.Prim.Int#, Int #) T18174.$wg1 - = \ (ww_s1a3 :: GHC.Prim.Int#) -> - case ww_s1a3 of ds_X2 { + = \ (ww_s1dz :: GHC.Prim.Int#) -> + case ww_s1dz of ds_X2 { __DEFAULT -> (# GHC.Prim.*# 2# ds_X2, case ds_X2 of wild_X3 { __DEFAULT -> let { - c1#_a17n :: GHC.Prim.Int# - c1#_a17n = GHC.Prim.andI# 1# (GHC.Prim.<# wild_X3 0#) } in - case GHC.Prim.quotInt# (GHC.Prim.-# 2# c1#_a17n) wild_X3 of wild1_a17o { __DEFAULT -> GHC.Types.I# (GHC.Prim.-# wild1_a17o c1#_a17n) }; + c1#_a1co :: GHC.Prim.Int# + c1#_a1co = GHC.Prim.andI# 1# (GHC.Prim.<# wild_X3 0#) } in + case GHC.Prim.-# (GHC.Prim.quotInt# (GHC.Prim.-# 2# c1#_a1co) wild_X3) c1#_a1co of ds2_a1aa { __DEFAULT -> GHC.Types.I# ds2_a1aa }; 0# -> GHC.Real.divZeroError @Int } #); 1# -> (# 15#, T18174.h5 #) @@ -203,52 +198,52 @@ T18174.$wg1 -- RHS size: {terms: 8, types: 9, coercions: 0, joins: 0/0} T18174.h4 :: (Int, Int) -T18174.h4 = case T18174.$wg1 2# of { (# ww_s1aW, ww1_s1a9 #) -> (GHC.Types.I# ww_s1aW, ww1_s1a9) } +T18174.h4 = case T18174.$wg1 2# of { (# ww_s1es, ww1_s1dE #) -> (GHC.Types.I# ww_s1es, ww1_s1dE) } -- RHS size: {terms: 22, types: 16, coercions: 0, joins: 0/0} T18174.$wh1 :: GHC.Prim.Int# -> Int T18174.$wh1 - = \ (ww_s1af :: GHC.Prim.Int#) -> - case ww_s1af of ds_X2 { - __DEFAULT -> case T18174.$wg1 ds_X2 of { (# ww1_s1aW, ww2_s1a9 #) -> case ww2_s1a9 of { GHC.Types.I# y_a17v -> GHC.Types.I# (GHC.Prim.+# ww1_s1aW y_a17v) } }; + = \ (ww_s1dL :: GHC.Prim.Int#) -> + case ww_s1dL of ds_X2 { + __DEFAULT -> case T18174.$wg1 ds_X2 of { (# ww1_s1es, ww2_s1dE #) -> case ww2_s1dE of { GHC.Types.I# y_a1ah -> GHC.Types.I# (GHC.Prim.+# ww1_s1es y_a1ah) } }; 1# -> T18174.h5; - 2# -> case T18174.h4 of { (ds1_a155, y_a156) -> y_a156 } + 2# -> case T18174.h4 of { (ds1_a1aS, y_a1aT) -> y_a1aT } } -- RHS size: {terms: 6, types: 3, coercions: 0, joins: 0/0} h1 :: Int -> Int -h1 = \ (ds_s1ad :: Int) -> case ds_s1ad of { GHC.Types.I# ww_s1af -> T18174.$wh1 ww_s1af } +h1 = \ (ds_s1dJ :: Int) -> case ds_s1dJ of { GHC.Types.I# ww_s1dL -> T18174.$wh1 ww_s1dL } -- RHS size: {terms: 12, types: 5, coercions: 0, joins: 0/0} thunkDiverges :: Int -> (Int, Bool) -thunkDiverges = \ (x_aIy :: Int) -> (case x_aIy of { GHC.Types.I# x1_a17s -> GHC.Types.I# (GHC.Prim.+# 2# (GHC.Prim.*# 2# x1_a17s)) }, GHC.Types.False) +thunkDiverges = \ (x_aLg :: Int) -> (case x_aLg of { GHC.Types.I# x1_a1ae -> GHC.Types.I# (GHC.Prim.+# 2# (GHC.Prim.*# 2# x1_a1ae)) }, GHC.Types.False) -- RHS size: {terms: 13, types: 10, coercions: 0, joins: 0/0} T18174.$wdataConWrapper :: (Int, Int) -> Int -> (# T, Int #) -T18174.$wdataConWrapper = \ (p_s1av :: (Int, Int)) (x_s1aw :: Int) -> (# T18174.$WMkT x_s1aw p_s1av, case x_s1aw of { GHC.Types.I# x1_a17s -> GHC.Types.I# (GHC.Prim.+# x1_a17s 1#) } #) +T18174.$wdataConWrapper = \ (p_s1e1 :: (Int, Int)) (x_s1e2 :: Int) -> (# T18174.$WMkT x_s1e2 p_s1e1, case x_s1e2 of { GHC.Types.I# x1_a1ae -> GHC.Types.I# (GHC.Prim.+# x1_a1ae 1#) } #) -- RHS size: {terms: 10, types: 13, coercions: 0, joins: 0/0} dataConWrapper :: (Int, Int) -> Int -> (T, Int) -dataConWrapper = \ (p_s1av :: (Int, Int)) (x_s1aw :: Int) -> case T18174.$wdataConWrapper p_s1av x_s1aw of { (# ww_s1aY, ww1_s1aZ #) -> (ww_s1aY, ww1_s1aZ) } +dataConWrapper = \ (p_s1e1 :: (Int, Int)) (x_s1e2 :: Int) -> case T18174.$wdataConWrapper p_s1e1 x_s1e2 of { (# ww_s1eu, ww1_s1ev #) -> (ww_s1eu, ww1_s1ev) } Rec { --- RHS size: {terms: 27, types: 31, coercions: 0, joins: 0/0} +-- RHS size: {terms: 27, types: 25, coercions: 0, joins: 0/0} T18174.$wfacIO :: GHC.Prim.Int# -> GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, Int #) T18174.$wfacIO - = \ (ww_s1aD :: GHC.Prim.Int#) (eta_s1aF :: GHC.Prim.State# GHC.Prim.RealWorld) -> - case GHC.Prim.<# ww_s1aD 2# of { - __DEFAULT -> case T18174.$wfacIO (GHC.Prim.-# ww_s1aD 1#) eta_s1aF of { (# ipv_a180, ipv1_a181 #) -> (# ipv_a180, case ipv1_a181 of { GHC.Types.I# y_a16I -> GHC.Types.I# (GHC.Prim.*# ww_s1aD y_a16I) } #) }; - 1# -> (# eta_s1aF, lvl_r1c8 #) + = \ (ww_s1e9 :: GHC.Prim.Int#) (eta_s1eb :: GHC.Prim.State# GHC.Prim.RealWorld) -> + case GHC.Prim.<# ww_s1e9 2# of { + __DEFAULT -> case T18174.$wfacIO (GHC.Prim.-# ww_s1e9 1#) eta_s1eb of { (# ipv_a1bb, ipv1_a1bc #) -> (# ipv_a1bb, case ipv1_a1bc of { GHC.Types.I# y_a19M -> GHC.Types.I# (GHC.Prim.*# ww_s1e9 y_a19M) } #) }; + 1# -> (# eta_s1eb, lvl_r1fX #) } end Rec } -- RHS size: {terms: 8, types: 5, coercions: 0, joins: 0/0} T18174.facIO1 :: Int -> GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, Int #) -T18174.facIO1 = \ (n_s1aB :: Int) (eta_s1aF :: GHC.Prim.State# GHC.Prim.RealWorld) -> case n_s1aB of { GHC.Types.I# ww_s1aD -> T18174.$wfacIO ww_s1aD eta_s1aF } +T18174.facIO1 = \ (n_s1e7 :: Int) (eta_s1eb :: GHC.Prim.State# GHC.Prim.RealWorld) -> case n_s1e7 of { GHC.Types.I# ww_s1e9 -> T18174.$wfacIO ww_s1e9 eta_s1eb } -- RHS size: {terms: 1, types: 0, coercions: 6, joins: 0/0} facIO :: Int -> IO Int -facIO = T18174.facIO1 `cast` (<Int>_R %<'Many>_N ->_R Sym (GHC.Types.N:IO[0] <Int>_R) :: (Int -> GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, Int #)) ~R# (Int -> IO Int)) +facIO = T18174.facIO1 `cast` (<Int>_R %<Many>_N ->_R Sym (GHC.Types.N:IO[0] <Int>_R) :: (Int -> GHC.Prim.State# GHC.Prim.RealWorld -> (# GHC.Prim.State# GHC.Prim.RealWorld, Int #)) ~R# (Int -> IO Int)) diff --git a/testsuite/tests/cpranal/should_compile/T18401.stderr b/testsuite/tests/cpranal/should_compile/T18401.stderr index 75913b39798157be7e0d4d38030083585cf58cc4..5993a2b07c313a7125a9ae2d866f270cd262d2c1 100644 --- a/testsuite/tests/cpranal/should_compile/T18401.stderr +++ b/testsuite/tests/cpranal/should_compile/T18401.stderr @@ -4,31 +4,31 @@ Result size of Tidy Core = {terms: 52, types: 86, coercions: 0, joins: 0/0} Rec { -- RHS size: {terms: 18, types: 24, coercions: 0, joins: 0/0} -T18401.$w$spoly_$wgo1 :: forall {a}. a -> [a] -> (# [a] #) +T18401.$w$spoly_$wgo1 :: forall a. a -> [a] -> (# [a] #) T18401.$w$spoly_$wgo1 - = \ (@a_s18C) (w_s18D :: a_s18C) (w1_s18E :: [a_s18C]) -> - case w1_s18E of { - [] -> (# GHC.Types.[] @a_s18C #); - : y_a15b ys_a15c -> (# GHC.Types.: @a_s18C w_s18D (case T18401.$w$spoly_$wgo1 @a_s18C y_a15b ys_a15c of { (# ww_s18J #) -> ww_s18J }) #) + = \ (@a_s1cL) (sc_s1cM :: a_s1cL) (sc1_s1cN :: [a_s1cL]) -> + case sc1_s1cN of { + [] -> (# GHC.Types.[] @a_s1cL #); + : y_a1bH ys_a1bI -> (# GHC.Types.: @a_s1cL sc_s1cM (case T18401.$w$spoly_$wgo1 @a_s1cL y_a1bH ys_a1bI of { (# ww_s1cR #) -> ww_s1cR }) #) } end Rec } -- RHS size: {terms: 17, types: 22, coercions: 0, joins: 0/0} si :: forall a. [a] -> (Bool, [a]) si - = \ (@a_s17T) (w_s17U :: [a_s17T]) -> - case w_s17U of { - [] -> (GHC.Types.False, GHC.Types.[] @a_s17T); - : y_a15b ys_a15c -> (GHC.Types.True, case T18401.$w$spoly_$wgo1 @a_s17T y_a15b ys_a15c of { (# ww_s18J #) -> ww_s18J }) + = \ (@a_s1bR) (xs0_s1bS :: [a_s1bR]) -> + case xs0_s1bS of { + [] -> (GHC.Types.False, GHC.Types.[] @a_s1bR); + : y_a1bH ys_a1bI -> (GHC.Types.True, case T18401.$w$spoly_$wgo1 @a_s1bR y_a1bH ys_a1bI of { (# ww_s1cR #) -> ww_s1cR }) } -- RHS size: {terms: 14, types: 19, coercions: 0, joins: 0/0} safeInit :: forall a. [a] -> Maybe [a] safeInit - = \ (@a_aPB) (xs_aut :: [a_aPB]) -> - case xs_aut of { - [] -> GHC.Maybe.Nothing @[a_aPB]; - : y_a15b ys_a15c -> GHC.Maybe.Just @[a_aPB] (case T18401.$w$spoly_$wgo1 @a_aPB y_a15b ys_a15c of { (# ww_s18J #) -> ww_s18J }) + = \ (@a_aQu) (xs_awN :: [a_aQu]) -> + case xs_awN of { + [] -> GHC.Maybe.Nothing @[a_aQu]; + : y_a1bH ys_a1bI -> GHC.Maybe.Just @[a_aQu] (case T18401.$w$spoly_$wgo1 @a_aQu y_a1bH ys_a1bI of { (# ww_s1cR #) -> ww_s1cR }) } diff --git a/testsuite/tests/pmcheck/should_compile/T11195.hs b/testsuite/tests/pmcheck/should_compile/T11195.hs index 7a7a4b05c5b47740e1e1eeba7d400609fbea6460..8b1c79c21911f93f2ac9f5a776451328abcfed67 100644 --- a/testsuite/tests/pmcheck/should_compile/T11195.hs +++ b/testsuite/tests/pmcheck/should_compile/T11195.hs @@ -111,11 +111,11 @@ opt_trans_rule is co1 co2@(AppCo co2a co2b) -- Push transitivity inside forall opt_trans_rule is co1 co2 - | ForAllCo tv1 eta1 r1 <- co1 - , Just (tv2,eta2,r2) <- etaForAllCo_maybe co2 = undefined + | ForAllCo tv1 vl1 vr1 eta1 r1 <- co1 + , Just (tv2,vl2,vr2,eta2,r2) <- etaForAllCo_maybe co2 = undefined - | ForAllCo tv2 eta2 r2 <- co2 - , Just (tv1,eta1,r1) <- etaForAllCo_maybe co1 = undefined + | ForAllCo tv2 vl2 vr1 eta2 r2 <- co2 + , Just (tv1,vl1,vr2,eta1,r1) <- etaForAllCo_maybe co1 = undefined where push_trans tv1 eta1 r1 tv2 eta2 r2 = undefined diff --git a/testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr b/testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr index 7c495e48fe0ee85c86e5a1068157814fb35c6aa5..8776aed758292331cf78fccd2d7a3327dc9daa5b 100644 --- a/testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr +++ b/testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr @@ -4,7 +4,7 @@ Result size of Tidy Core = {terms: 82, types: 52, coercions: 29, joins: 0/0} -- RHS size: {terms: 3, types: 3, coercions: 0, joins: 0/0} -unsafeToInteger1 :: forall {n :: Nat}. Signed n -> Signed n +unsafeToInteger1 :: forall (n :: Nat). Signed n -> Signed n [GblId, Arity=1, Unf=OtherCon []] unsafeToInteger1 = \ (@(n :: Nat)) (ds :: Signed n) -> ds @@ -15,8 +15,8 @@ unsafeToInteger = unsafeToInteger1 `cast` (forall (n :: <Nat>_N). <Signed n>_R %<Many>_N ->_R OpaqueNoCastWW.N:Signed[0] <n>_P - :: (forall {n :: Nat}. Signed n -> Signed n) - ~R# (forall {n :: Nat}. Signed n -> Integer)) + :: (forall (n :: Nat). Signed n -> Signed n) + ~R# (forall (n :: Nat). Signed n -> Integer)) -- RHS size: {terms: 8, types: 7, coercions: 21, joins: 0/0} times [InlPrag=OPAQUE] @@ -38,8 +38,8 @@ times <Signed m>_R %<Many>_N ->_R <Signed n>_R %<Many>_N ->_R Sym (OpaqueNoCastWW.N:Signed[0] <m + n>_P) - :: (forall {m :: Nat} {n :: Nat}. Signed m -> Signed n -> Integer) - ~R# (forall {m :: Nat} {n :: Nat}. + :: (forall (m :: Nat) (n :: Nat). Signed m -> Signed n -> Integer) + ~R# (forall (m :: Nat) (n :: Nat). Signed m -> Signed n -> Signed (m + n))) -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} diff --git a/testsuite/tests/stranal/should_compile/T15627.stderr b/testsuite/tests/stranal/should_compile/T15627.stderr index 38c054da179d0d19762ea8a187e3bd8477e721bf..02520ebd719bf3fee6cea4085ce11af99b660e65 100644 --- a/testsuite/tests/stranal/should_compile/T15627.stderr +++ b/testsuite/tests/stranal/should_compile/T15627.stderr @@ -1,337 +1,320 @@ -[1 of 1] Compiling Unlifted ( T15627.hs, T15627.o ) ==================== Tidy Core ==================== -Result size of Tidy Core = {terms: 254, types: 130, coercions: 0, joins: 3/3} +Result size of Tidy Core = {terms: 266, types: 128, coercions: 0, joins: 3/3} -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} Unlifted.$trModule4 :: Addr# -[GblId, - Caf=NoCafRefs, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 20 0}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 20 0}] Unlifted.$trModule4 = "main"# -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} Unlifted.$trModule3 :: GHC.Types.TrName -[GblId, - Caf=NoCafRefs, - Str=m1, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$trModule3 = GHC.Types.TrNameS Unlifted.$trModule4 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} Unlifted.$trModule2 :: Addr# -[GblId, - Caf=NoCafRefs, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] Unlifted.$trModule2 = "Unlifted"# -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} Unlifted.$trModule1 :: GHC.Types.TrName -[GblId, - Caf=NoCafRefs, - Str=m1, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$trModule1 = GHC.Types.TrNameS Unlifted.$trModule2 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -Unlifted.$trModule :: GHC.Unit.Module -[GblId, - Caf=NoCafRefs, - Str=m, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 30}] -Unlifted.$trModule = GHC.Unit.Module Unlifted.$trModule3 Unlifted.$trModule1 +Unlifted.$trModule :: GHC.Types.Module +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] +Unlifted.$trModule = GHC.Types.Module Unlifted.$trModule3 Unlifted.$trModule1 + +-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} +$krep_r1d0 :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep_r1d0 = GHC.Types.KindRepTyConApp GHC.Types.$tc'Lifted (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} -$krep_r2Xd :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []] -$krep_r2Xd = GHC.Types.KindRepTyConApp GHC.Types.$tcInt (GHC.Types.[] @ GHC.Types.KindRep) +$krep1_r1d1 :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep1_r1d1 = GHC.Types.KindRepTyConApp GHC.Types.$tcInt (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} -$krep1_r2Xe :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []] -$krep1_r2Xe = GHC.Types.KindRepVar 1# +$krep2_r1d2 :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep2_r1d2 = GHC.Types.KindRepVar 1# -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} -$krep2_r2Xf :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []] -$krep2_r2Xf = GHC.Types.KindRepVar 0# +$krep3_r1d3 :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep3_r1d3 = GHC.Types.KindRepVar 0# -- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0} -$krep3_r2Xg :: [GHC.Types.KindRep] -[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []] -$krep3_r2Xg = GHC.Types.: @ GHC.Types.KindRep $krep2_r2Xf (GHC.Types.[] @ GHC.Types.KindRep) +$krep4_r1d4 :: [GHC.Types.KindRep] +[GblId, Unf=OtherCon []] +$krep4_r1d4 = GHC.Types.: @GHC.Types.KindRep $krep3_r1d3 (GHC.Types.[] @GHC.Types.KindRep) + +-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} +$krep5_r1d5 :: [GHC.Types.KindRep] +[GblId, Unf=OtherCon []] +$krep5_r1d5 = GHC.Types.: @GHC.Types.KindRep $krep_r1d0 $krep4_r1d4 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep4_r2Xh :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []] -$krep4_r2Xh = GHC.Types.KindRepTyConApp GHC.Types.$tcArray# $krep3_r2Xg +$krep6_r1d6 :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep6_r1d6 = GHC.Types.KindRepTyConApp GHC.Types.$tcArray# $krep5_r1d5 -- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0} -$krep5_r2Xi :: [GHC.Types.KindRep] -[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []] -$krep5_r2Xi = GHC.Types.: @ GHC.Types.KindRep $krep1_r2Xe (GHC.Types.[] @ GHC.Types.KindRep) +$krep7_r1d7 :: [GHC.Types.KindRep] +[GblId, Unf=OtherCon []] +$krep7_r1d7 = GHC.Types.: @GHC.Types.KindRep $krep2_r1d2 (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} -$krep6_r2Xj :: [GHC.Types.KindRep] -[GblId, Caf=NoCafRefs, Str=m2, Unf=OtherCon []] -$krep6_r2Xj = GHC.Types.: @ GHC.Types.KindRep $krep2_r2Xf $krep5_r2Xi +$krep8_r1d8 :: [GHC.Types.KindRep] +[GblId, Unf=OtherCon []] +$krep8_r1d8 = GHC.Types.: @GHC.Types.KindRep $krep3_r1d3 $krep7_r1d7 + +-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} +$krep9_r1d9 :: [GHC.Types.KindRep] +[GblId, Unf=OtherCon []] +$krep9_r1d9 = GHC.Types.: @GHC.Types.KindRep $krep_r1d0 $krep8_r1d8 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep7_r2Xk :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []] -$krep7_r2Xk = GHC.Types.KindRepTyConApp GHC.Types.$tcMutVar# $krep6_r2Xj +$krep10_r1da :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep10_r1da = GHC.Types.KindRepTyConApp GHC.Types.$tcMutVar# $krep9_r1d9 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} Unlifted.$tcMMutVar2 :: Addr# -[GblId, - Caf=NoCafRefs, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] Unlifted.$tcMMutVar2 = "MMutVar"# -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} Unlifted.$tcMMutVar1 :: GHC.Types.TrName -[GblId, - Caf=NoCafRefs, - Str=m1, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tcMMutVar1 = GHC.Types.TrNameS Unlifted.$tcMMutVar2 -- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0} Unlifted.$tcMMutVar :: GHC.Types.TyCon -[GblId, - Caf=NoCafRefs, - Str=m, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 70}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tcMMutVar - = GHC.Types.TyCon 976071122164149049## 18076036821450447502## Unlifted.$trModule Unlifted.$tcMMutVar1 0# GHC.Types.krep$*->*->* + = GHC.Types.TyCon + 976071122164149049#Word64 18076036821450447502#Word64 Unlifted.$trModule Unlifted.$tcMMutVar1 0# GHC.Types.krep$*->*->* -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep8_r2Xl :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []] -$krep8_r2Xl = GHC.Types.KindRepTyConApp Unlifted.$tcMMutVar $krep6_r2Xj +$krep11_r1db :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep11_r1db = GHC.Types.KindRepTyConApp Unlifted.$tcMMutVar $krep8_r1d8 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep9_r2Xm :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m4, Unf=OtherCon []] -$krep9_r2Xm = GHC.Types.KindRepFun $krep_r2Xd $krep8_r2Xl +$krep12_r1dc :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep12_r1dc = GHC.Types.KindRepFun $krep1_r1d1 $krep11_r1db -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -Unlifted.$tc'MMutVar1 [InlPrag=NOUSERINLINE[~]] :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m4, Unf=OtherCon []] -Unlifted.$tc'MMutVar1 = GHC.Types.KindRepFun $krep7_r2Xk $krep9_r2Xm +Unlifted.$tc'MMutVar1 [InlPrag=[~]] :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +Unlifted.$tc'MMutVar1 = GHC.Types.KindRepFun $krep10_r1da $krep12_r1dc -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} Unlifted.$tc'MMutVar3 :: Addr# -[GblId, - Caf=NoCafRefs, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] Unlifted.$tc'MMutVar3 = "'MMutVar"# -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} Unlifted.$tc'MMutVar2 :: GHC.Types.TrName -[GblId, - Caf=NoCafRefs, - Str=m1, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tc'MMutVar2 = GHC.Types.TrNameS Unlifted.$tc'MMutVar3 -- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0} Unlifted.$tc'MMutVar :: GHC.Types.TyCon -[GblId, - Caf=NoCafRefs, - Str=m, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 70}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tc'MMutVar - = GHC.Types.TyCon 1807347364283186211## 6245494011022471830## Unlifted.$trModule Unlifted.$tc'MMutVar2 2# Unlifted.$tc'MMutVar1 + = GHC.Types.TyCon + 1807347364283186211#Word64 6245494011022471830#Word64 Unlifted.$trModule Unlifted.$tc'MMutVar2 2# Unlifted.$tc'MMutVar1 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} Unlifted.$tcAArray2 :: Addr# -[GblId, - Caf=NoCafRefs, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] Unlifted.$tcAArray2 = "AArray"# -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} Unlifted.$tcAArray1 :: GHC.Types.TrName -[GblId, - Caf=NoCafRefs, - Str=m1, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tcAArray1 = GHC.Types.TrNameS Unlifted.$tcAArray2 -- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0} Unlifted.$tcAArray :: GHC.Types.TyCon -[GblId, - Caf=NoCafRefs, - Str=m, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 70}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tcAArray - = GHC.Types.TyCon 15463012197909582608## 8369862272173810511## Unlifted.$trModule Unlifted.$tcAArray1 0# GHC.Types.krep$*Arr* + = GHC.Types.TyCon + 15463012197909582608#Word64 8369862272173810511#Word64 Unlifted.$trModule Unlifted.$tcAArray1 0# GHC.Types.krep$*Arr* -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep10_r2Xn :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m1, Unf=OtherCon []] -$krep10_r2Xn = GHC.Types.KindRepTyConApp Unlifted.$tcAArray $krep3_r2Xg +$krep13_r1dd :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep13_r1dd = GHC.Types.KindRepTyConApp Unlifted.$tcAArray $krep4_r1d4 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep11_r2Xo :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m4, Unf=OtherCon []] -$krep11_r2Xo = GHC.Types.KindRepFun $krep_r2Xd $krep10_r2Xn +$krep14_r1de :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +$krep14_r1de = GHC.Types.KindRepFun $krep1_r1d1 $krep13_r1dd -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -Unlifted.$tc'AArray1 [InlPrag=NOUSERINLINE[~]] :: GHC.Types.KindRep -[GblId, Caf=NoCafRefs, Str=m4, Unf=OtherCon []] -Unlifted.$tc'AArray1 = GHC.Types.KindRepFun $krep4_r2Xh $krep11_r2Xo +Unlifted.$tc'AArray1 [InlPrag=[~]] :: GHC.Types.KindRep +[GblId, Unf=OtherCon []] +Unlifted.$tc'AArray1 = GHC.Types.KindRepFun $krep6_r1d6 $krep14_r1de -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} Unlifted.$tc'AArray3 :: Addr# -[GblId, - Caf=NoCafRefs, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 30 0}] Unlifted.$tc'AArray3 = "'AArray"# -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} Unlifted.$tc'AArray2 :: GHC.Types.TrName -[GblId, - Caf=NoCafRefs, - Str=m1, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tc'AArray2 = GHC.Types.TrNameS Unlifted.$tc'AArray3 -- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0} Unlifted.$tc'AArray :: GHC.Types.TyCon -[GblId, - Caf=NoCafRefs, - Str=m, - Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 70}] +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] Unlifted.$tc'AArray - = GHC.Types.TyCon 5117353292610538775## 18288923674485681885## Unlifted.$trModule Unlifted.$tc'AArray2 1# Unlifted.$tc'AArray1 + = GHC.Types.TyCon + 5117353292610538775#Word64 18288923674485681885#Word64 Unlifted.$trModule Unlifted.$tc'AArray2 1# Unlifted.$tc'AArray1 -- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0} -lvl_r2Xp :: Int -[GblId, Caf=NoCafRefs, Str=m, Unf=OtherCon []] -lvl_r2Xp = GHC.Types.I# 1# +Unlifted.fac1 :: Int +[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}] +Unlifted.fac1 = GHC.Types.I# 1# -- RHS size: {terms: 34, types: 10, coercions: 0, joins: 1/1} -fac [InlPrag=NOUSERINLINE[2]] :: Int -> Int +fac :: Int -> Int [GblId, Arity=1, - Caf=NoCafRefs, - Str=<S(S),1*U(U)>m, - Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, + Str=<1!P(L)>, + Cpr=1, + Unf=Unf{Src=StableSystem, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False) - Tmpl= \ (w_s2UI [Occ=Once!] :: Int) -> - case w_s2UI of { I# ww1_s2UL -> - case ># 1# ww1_s2UL of { + Tmpl= \ (n_ayj [Occ=Once1!] :: Int) -> + case n_ayj of { I# y_a1bo -> + case ># 1# y_a1bo of { __DEFAULT -> joinrec { - $wgo_s2UH [InlPrag=NOUSERINLINE[2], Occ=LoopBreakerT[2]] :: Int# -> Int# -> Int - [LclId[JoinId(2)], Arity=2, Str=<S,U><S,U>m, Unf=OtherCon []] - $wgo_s2UH (w1_s2UB :: Int#) (ww2_s2UF [Occ=Once*] :: Int#) - = case ==# w1_s2UB ww1_s2UL of { - __DEFAULT -> jump $wgo_s2UH (+# w1_s2UB 1#) (*# ww2_s2UF w1_s2UB); - 1# -> GHC.Types.I# (*# ww2_s2UF w1_s2UB) + go3_a1bC [InlPrag=[2], Occ=T[2]] :: Int# -> Int -> Int + [LclId[JoinId(2)(Just [~, !])], + Arity=2, + Str=<L><S!P(L)>, + Unf=Unf{Src=StableSystem, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, + Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False) + Tmpl= \ (x_s1bI [Occ=Once1] :: Int#) (v_s1bJ [Occ=Once1!, OS=OneShot] :: Int) -> + case v_s1bJ of { I# ww_s1bL [Occ=Once1] -> jump $wgo3_s1bO x_s1bI ww_s1bL }}] + go3_a1bC (x_s1bI [Occ=Once1] :: Int#) (v_s1bJ [Occ=Once1!, OS=OneShot] :: Int) + = case v_s1bJ of { I# ww_s1bL [Occ=Once1] -> jump $wgo3_s1bO x_s1bI ww_s1bL }; + $wgo3_s1bO [InlPrag=[2], Occ=LoopBreakerT[2]] :: Int# -> Int# -> Int + [LclId[JoinId(2)(Nothing)], Arity=2, Str=<L><L>, Unf=OtherCon []] + $wgo3_s1bO (x_s1bI :: Int#) (ww_s1bL [Occ=Once2] :: Int#) + = case ==# x_s1bI y_a1bo of { + __DEFAULT -> jump go3_a1bC (+# x_s1bI 1#) (GHC.Types.I# (*# ww_s1bL x_s1bI)); + 1# -> GHC.Types.I# (*# ww_s1bL x_s1bI) }; } in - jump $wgo_s2UH 1# 1#; - 1# -> GHC.Types.I# 1# + jump go3_a1bC 1# Unlifted.fac1; + 1# -> Unlifted.fac1 } }}] fac - = \ (w_s2UI :: Int) -> - case w_s2UI of { I# ww1_s2UL -> - case ># 1# ww1_s2UL of { + = \ (n_ayj :: Int) -> + case n_ayj of { I# y_a1bo -> + case ># 1# y_a1bo of { __DEFAULT -> joinrec { - $wgo_s2UH [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker] :: Int# -> Int# -> Int - [LclId[JoinId(2)], Arity=2, Str=<S,U><S,U>m, Unf=OtherCon []] - $wgo_s2UH (w1_s2UB :: Int#) (ww2_s2UF :: Int#) - = case ==# w1_s2UB ww1_s2UL of { - __DEFAULT -> jump $wgo_s2UH (+# w1_s2UB 1#) (*# ww2_s2UF w1_s2UB); - 1# -> GHC.Types.I# (*# ww2_s2UF w1_s2UB) + $wgo3_s1bO [InlPrag=[2], Occ=LoopBreaker, Dmd=SC(S,C(1,!P(L)))] :: Int# -> Int# -> Int + [LclId[JoinId(2)(Nothing)], Arity=2, Str=<L><L>, Unf=OtherCon []] + $wgo3_s1bO (x_s1bI :: Int#) (ww_s1bL :: Int#) + = case ==# x_s1bI y_a1bo of { + __DEFAULT -> jump $wgo3_s1bO (+# x_s1bI 1#) (*# ww_s1bL x_s1bI); + 1# -> GHC.Types.I# (*# ww_s1bL x_s1bI) }; } in - jump $wgo_s2UH 1# 1#; - 1# -> lvl_r2Xp + jump $wgo3_s1bO 1# 1#; + 1# -> Unlifted.fac1 } } --- RHS size: {terms: 32, types: 12, coercions: 0, joins: 1/1} -Unlifted.$wmutVar [InlPrag=NOINLINE] :: forall {s} {a}. Int# -> Int# -[GblId, Arity=1, Caf=NoCafRefs, Str=<S,U>, Unf=OtherCon []] +-- RHS size: {terms: 32, types: 10, coercions: 0, joins: 1/1} +Unlifted.$wmutVar [InlPrag=NOINLINE] :: forall s a. Int# -> Int# +[GblId, Arity=1, Str=<L>, Unf=OtherCon []] Unlifted.$wmutVar - = \ (@ s_s2UR) (@ a_s2US) (ww_s2V0 :: Int#) -> - case ># 1# ww_s2V0 of { + = \ (@s_s1bX) (@a_s1bY) (ww_s1c4 :: Int#) -> + case ># 1# ww_s1c4 of { __DEFAULT -> joinrec { - $wgo_s2UH [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker] :: Int# -> Int# -> Int# - [LclId[JoinId(2)], Arity=2, Str=<S,U><S,U>, Unf=OtherCon []] - $wgo_s2UH (w_s2UB :: Int#) (ww1_s2UF :: Int#) - = case ==# w_s2UB ww_s2V0 of { - __DEFAULT -> jump $wgo_s2UH (+# w_s2UB 1#) (*# ww1_s2UF w_s2UB); - 1# -> *# ww1_s2UF w_s2UB + $wgo3_s1bO [InlPrag=[2], Occ=LoopBreaker, Dmd=SC(S,C(1,L))] :: Int# -> Int# -> Int# + [LclId[JoinId(2)(Nothing)], Arity=2, Str=<L><L>, Unf=OtherCon []] + $wgo3_s1bO (x_s1bI :: Int#) (ww1_s1bL :: Int#) + = case ==# x_s1bI ww_s1c4 of { + __DEFAULT -> jump $wgo3_s1bO (+# x_s1bI 1#) (*# ww1_s1bL x_s1bI); + 1# -> *# ww1_s1bL x_s1bI }; } in - jump $wgo_s2UH 1# 1#; + jump $wgo3_s1bO 1# 1#; 1# -> 1# } --- RHS size: {terms: 15, types: 19, coercions: 0, joins: 0/0} -mutVar [InlPrag=NOUSERINLINE[0]] :: forall s a. MMutVar s a -> Int +-- RHS size: {terms: 15, types: 18, coercions: 0, joins: 0/0} +mutVar [InlPrag=NOINLINE[final]] :: forall s a. MMutVar s a -> Int [GblId, Arity=1, - Caf=NoCafRefs, - Str=<S(LS(S)),1*U(A,1*U(U))>m, - Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, + Str=<1!P(A,1!P(L))>, + Cpr=1, + Unf=Unf{Src=StableSystem, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False) - Tmpl= \ (@ s_s2UR) (@ a_s2US) (w_s2UT [Occ=Once!] :: MMutVar s_s2UR a_s2US) -> - case w_s2UT of { MMutVar _ [Occ=Dead] ww2_s2UX [Occ=Once!] -> - case ww2_s2UX of { I# ww4_s2V0 [Occ=Once] -> - case Unlifted.$wmutVar @ s_s2UR @ a_s2US ww4_s2V0 of ww5_s2V5 [Occ=Once] { __DEFAULT -> GHC.Types.I# ww5_s2V5 } + Tmpl= \ (@s_s1bX) (@a_s1bY) (ds_s1bZ [Occ=Once1!] :: MMutVar s_s1bX a_s1bY) -> + case ds_s1bZ of { MMutVar _ [Occ=Dead] ww1_s1c2 [Occ=Once1!] -> + case ww1_s1c2 of { I# ww2_s1c4 [Occ=Once1] -> + case Unlifted.$wmutVar @s_s1bX @a_s1bY ww2_s1c4 of ww3_s1cn [Occ=Once1] { __DEFAULT -> GHC.Types.I# ww3_s1cn } } }}] mutVar - = \ (@ s_s2UR) (@ a_s2US) (w_s2UT :: MMutVar s_s2UR a_s2US) -> - case w_s2UT of { MMutVar ww1_s2UW ww2_s2UX -> - case ww2_s2UX of { I# ww4_s2V0 -> - case Unlifted.$wmutVar @ s_s2UR @ a_s2US ww4_s2V0 of ww5_s2V5 { __DEFAULT -> GHC.Types.I# ww5_s2V5 } + = \ (@s_s1bX) (@a_s1bY) (ds_s1bZ :: MMutVar s_s1bX a_s1bY) -> + case ds_s1bZ of { MMutVar ww_s1c1 ww1_s1c2 -> + case ww1_s1c2 of { I# ww2_s1c4 -> + case Unlifted.$wmutVar @s_s1bX @a_s1bY ww2_s1c4 of ww3_s1cn { __DEFAULT -> GHC.Types.I# ww3_s1cn } } } --- RHS size: {terms: 31, types: 10, coercions: 0, joins: 1/1} -Unlifted.$warray [InlPrag=NOINLINE] :: forall {a}. Int# -> Int# -[GblId, Arity=1, Caf=NoCafRefs, Str=<S,U>, Unf=OtherCon []] +-- RHS size: {terms: 31, types: 9, coercions: 0, joins: 1/1} +Unlifted.$warray [InlPrag=NOINLINE] :: forall a. Int# -> Int# +[GblId, Arity=1, Str=<L>, Unf=OtherCon []] Unlifted.$warray - = \ (@ a_s2V7) (ww_s2Vf :: Int#) -> - case ># 1# ww_s2Vf of { + = \ (@a_s1cb) (ww_s1ch :: Int#) -> + case ># 1# ww_s1ch of { __DEFAULT -> joinrec { - $wgo_s2UH [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker] :: Int# -> Int# -> Int# - [LclId[JoinId(2)], Arity=2, Str=<S,U><S,U>, Unf=OtherCon []] - $wgo_s2UH (w_s2UB :: Int#) (ww1_s2UF :: Int#) - = case ==# w_s2UB ww_s2Vf of { - __DEFAULT -> jump $wgo_s2UH (+# w_s2UB 1#) (*# ww1_s2UF w_s2UB); - 1# -> *# ww1_s2UF w_s2UB + $wgo3_s1bO [InlPrag=[2], Occ=LoopBreaker, Dmd=SC(S,C(1,L))] :: Int# -> Int# -> Int# + [LclId[JoinId(2)(Nothing)], Arity=2, Str=<L><L>, Unf=OtherCon []] + $wgo3_s1bO (x_s1bI :: Int#) (ww1_s1bL :: Int#) + = case ==# x_s1bI ww_s1ch of { + __DEFAULT -> jump $wgo3_s1bO (+# x_s1bI 1#) (*# ww1_s1bL x_s1bI); + 1# -> *# ww1_s1bL x_s1bI }; } in - jump $wgo_s2UH 1# 1#; + jump $wgo3_s1bO 1# 1#; 1# -> 1# } -- RHS size: {terms: 14, types: 13, coercions: 0, joins: 0/0} -array [InlPrag=NOUSERINLINE[0]] :: forall a. AArray a -> Int +array [InlPrag=NOINLINE[final]] :: forall a. AArray a -> Int [GblId, Arity=1, - Caf=NoCafRefs, - Str=<S(LS(S)),1*U(A,1*U(U))>m, - Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, + Str=<1!P(A,1!P(L))>, + Cpr=1, + Unf=Unf{Src=StableSystem, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False) - Tmpl= \ (@ a_s2V7) (w_s2V8 [Occ=Once!] :: AArray a_s2V7) -> - case w_s2V8 of { AArray _ [Occ=Dead] ww2_s2Vc [Occ=Once!] -> - case ww2_s2Vc of { I# ww4_s2Vf [Occ=Once] -> - case Unlifted.$warray @ a_s2V7 ww4_s2Vf of ww5_s2Vk [Occ=Once] { __DEFAULT -> GHC.Types.I# ww5_s2Vk } + Tmpl= \ (@a_s1cb) (ds_s1cc [Occ=Once1!] :: AArray a_s1cb) -> + case ds_s1cc of { AArray _ [Occ=Dead] ww1_s1cf [Occ=Once1!] -> + case ww1_s1cf of { I# ww2_s1ch [Occ=Once1] -> + case Unlifted.$warray @a_s1cb ww2_s1ch of ww3_s1cp [Occ=Once1] { __DEFAULT -> GHC.Types.I# ww3_s1cp } } }}] array - = \ (@ a_s2V7) (w_s2V8 :: AArray a_s2V7) -> - case w_s2V8 of { AArray ww1_s2Vb ww2_s2Vc -> - case ww2_s2Vc of { I# ww4_s2Vf -> case Unlifted.$warray @ a_s2V7 ww4_s2Vf of ww5_s2Vk { __DEFAULT -> GHC.Types.I# ww5_s2Vk } } + = \ (@a_s1cb) (ds_s1cc :: AArray a_s1cb) -> + case ds_s1cc of { AArray ww_s1ce ww1_s1cf -> + case ww1_s1cf of { I# ww2_s1ch -> case Unlifted.$warray @a_s1cb ww2_s1ch of ww3_s1cp { __DEFAULT -> GHC.Types.I# ww3_s1cp } } } diff --git a/testsuite/tests/stranal/should_compile/T18982.stderr b/testsuite/tests/stranal/should_compile/T18982.stderr index 4d1606cba97e90f02c02db201d11e7d292e024a7..6e1be6b724eea8c9007b46aef0bab328481b2408 100644 --- a/testsuite/tests/stranal/should_compile/T18982.stderr +++ b/testsuite/tests/stranal/should_compile/T18982.stderr @@ -1,10 +1,10 @@ ==================== Tidy Core ==================== -Result size of Tidy Core = {terms: 311, types: 214, coercions: 4, joins: 0/0} +Result size of Tidy Core = {terms: 295, types: 206, coercions: 4, joins: 0/0} -- RHS size: {terms: 8, types: 9, coercions: 1, joins: 0/0} T18982.$WExGADT :: forall e. (e ~ Int) => e %1 -> Int %1 -> ExGADT Int -T18982.$WExGADT = \ (@e) (conrep :: e ~ Int) (conrep :: e) (conrep :: Int) -> T18982.ExGADT @Int @e @~(<Int>_N :: Int GHC.Prim.~# Int) conrep conrep conrep +T18982.$WExGADT = \ (@e) (conrep :: e ~ Int) (conrep1 :: e) (conrep2 :: Int) -> T18982.ExGADT @Int @e @~(<Int>_N :: Int GHC.Prim.~# Int) conrep conrep1 conrep2 -- RHS size: {terms: 3, types: 2, coercions: 1, joins: 0/0} T18982.$WGADT :: Int %1 -> GADT Int @@ -12,7 +12,7 @@ T18982.$WGADT = \ (conrep :: Int) -> T18982.GADT @Int @~(<Int>_N :: Int GHC.Prim -- RHS size: {terms: 7, types: 6, coercions: 0, joins: 0/0} T18982.$WEx :: forall e a. e %1 -> a %1 -> Ex a -T18982.$WEx = \ (@e) (@a) (conrep :: e) (conrep :: a) -> T18982.Ex @a @e conrep conrep +T18982.$WEx = \ (@e) (@a) (conrep :: e) (conrep1 :: a) -> T18982.Ex @a @e conrep conrep1 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18982.$trModule4 :: GHC.Prim.Addr# @@ -46,22 +46,6 @@ $krep1 = GHC.Types.KindRepVar 1# $krep2 :: GHC.Types.KindRep $krep2 = GHC.Types.KindRepVar 0# --- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0} -$krep3 :: [GHC.Types.KindRep] -$krep3 = GHC.Types.: @GHC.Types.KindRep $krep (GHC.Types.[] @GHC.Types.KindRep) - --- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} -$krep4 :: [GHC.Types.KindRep] -$krep4 = GHC.Types.: @GHC.Types.KindRep $krep2 $krep3 - --- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0} -$krep5 :: [GHC.Types.KindRep] -$krep5 = GHC.Types.: @GHC.Types.KindRep GHC.Types.krep$* $krep4 - --- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep6 :: GHC.Types.KindRep -$krep6 = GHC.Types.KindRepTyConApp GHC.Types.$tc~ $krep5 - -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18982.$tcBox2 :: GHC.Prim.Addr# T18982.$tcBox2 = "Box"# @@ -75,16 +59,16 @@ T18982.$tcBox :: GHC.Types.TyCon T18982.$tcBox = GHC.Types.TyCon 16948648223906549518#Word64 2491460178135962649#Word64 T18982.$trModule T18982.$tcBox1 0# GHC.Types.krep$*Arr* -- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0} -$krep7 :: [GHC.Types.KindRep] -$krep7 = GHC.Types.: @GHC.Types.KindRep $krep2 (GHC.Types.[] @GHC.Types.KindRep) +$krep3 :: [GHC.Types.KindRep] +$krep3 = GHC.Types.: @GHC.Types.KindRep $krep2 (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep8 :: GHC.Types.KindRep -$krep8 = GHC.Types.KindRepTyConApp T18982.$tcBox $krep7 +$krep4 :: GHC.Types.KindRep +$krep4 = GHC.Types.KindRepTyConApp T18982.$tcBox $krep3 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} T18982.$tc'Box1 :: GHC.Types.KindRep -T18982.$tc'Box1 = GHC.Types.KindRepFun $krep2 $krep8 +T18982.$tc'Box1 = GHC.Types.KindRepFun $krep2 $krep4 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18982.$tc'Box3 :: GHC.Prim.Addr# @@ -111,20 +95,20 @@ T18982.$tcEx :: GHC.Types.TyCon T18982.$tcEx = GHC.Types.TyCon 4376661818164435927#Word64 18005417598910668817#Word64 T18982.$trModule T18982.$tcEx1 0# GHC.Types.krep$*Arr* -- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0} -$krep9 :: [GHC.Types.KindRep] -$krep9 = GHC.Types.: @GHC.Types.KindRep $krep1 (GHC.Types.[] @GHC.Types.KindRep) +$krep5 :: [GHC.Types.KindRep] +$krep5 = GHC.Types.: @GHC.Types.KindRep $krep1 (GHC.Types.[] @GHC.Types.KindRep) -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep10 :: GHC.Types.KindRep -$krep10 = GHC.Types.KindRepTyConApp T18982.$tcEx $krep9 +$krep6 :: GHC.Types.KindRep +$krep6 = GHC.Types.KindRepTyConApp T18982.$tcEx $krep5 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep11 :: GHC.Types.KindRep -$krep11 = GHC.Types.KindRepFun $krep1 $krep10 +$krep7 :: GHC.Types.KindRep +$krep7 = GHC.Types.KindRepFun $krep1 $krep6 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} T18982.$tc'Ex1 :: GHC.Types.KindRep -T18982.$tc'Ex1 = GHC.Types.KindRepFun $krep2 $krep11 +T18982.$tc'Ex1 = GHC.Types.KindRepFun $krep2 $krep7 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18982.$tc'Ex3 :: GHC.Prim.Addr# @@ -150,13 +134,17 @@ T18982.$tcGADT1 = GHC.Types.TrNameS T18982.$tcGADT2 T18982.$tcGADT :: GHC.Types.TyCon T18982.$tcGADT = GHC.Types.TyCon 9243924476135839950#Word64 5096619276488416461#Word64 T18982.$trModule T18982.$tcGADT1 0# GHC.Types.krep$*Arr* +-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0} +$krep8 :: [GHC.Types.KindRep] +$krep8 = GHC.Types.: @GHC.Types.KindRep $krep (GHC.Types.[] @GHC.Types.KindRep) + -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep12 :: GHC.Types.KindRep -$krep12 = GHC.Types.KindRepTyConApp T18982.$tcGADT $krep3 +$krep9 :: GHC.Types.KindRep +$krep9 = GHC.Types.KindRepTyConApp T18982.$tcGADT $krep8 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} T18982.$tc'GADT1 :: GHC.Types.KindRep -T18982.$tc'GADT1 = GHC.Types.KindRepFun $krep $krep12 +T18982.$tc'GADT1 = GHC.Types.KindRepFun $krep $krep9 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18982.$tc'GADT3 :: GHC.Prim.Addr# @@ -183,20 +171,16 @@ T18982.$tcExGADT :: GHC.Types.TyCon T18982.$tcExGADT = GHC.Types.TyCon 6470898418160489500#Word64 10361108917441214060#Word64 T18982.$trModule T18982.$tcExGADT1 0# GHC.Types.krep$*Arr* -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep13 :: GHC.Types.KindRep -$krep13 = GHC.Types.KindRepTyConApp T18982.$tcExGADT $krep3 - --- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep14 :: GHC.Types.KindRep -$krep14 = GHC.Types.KindRepFun $krep $krep13 +$krep10 :: GHC.Types.KindRep +$krep10 = GHC.Types.KindRepTyConApp T18982.$tcExGADT $krep8 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} -$krep15 :: GHC.Types.KindRep -$krep15 = GHC.Types.KindRepFun $krep2 $krep14 +$krep11 :: GHC.Types.KindRep +$krep11 = GHC.Types.KindRepFun $krep $krep10 -- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0} T18982.$tc'ExGADT1 :: GHC.Types.KindRep -T18982.$tc'ExGADT1 = GHC.Types.KindRepFun $krep6 $krep15 +T18982.$tc'ExGADT1 = GHC.Types.KindRepFun $krep2 $krep11 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0} T18982.$tc'ExGADT3 :: GHC.Prim.Addr# @@ -211,7 +195,7 @@ T18982.$tc'ExGADT :: GHC.Types.TyCon T18982.$tc'ExGADT = GHC.Types.TyCon 8468257409157161049#Word64 5503123603717080600#Word64 T18982.$trModule T18982.$tc'ExGADT2 1# T18982.$tc'ExGADT1 -- RHS size: {terms: 11, types: 10, coercions: 0, joins: 0/0} -T18982.$wi :: forall {a} {e}. (a GHC.Prim.~# Int) => e -> GHC.Prim.Int# -> GHC.Prim.Int# +T18982.$wi :: forall a e. (a GHC.Prim.~# Int) => e -> GHC.Prim.Int# -> GHC.Prim.Int# T18982.$wi = \ (@a) (@e) (ww :: a GHC.Prim.~# Int) (ww1 :: e) (ww2 :: GHC.Prim.Int#) -> case ww1 of { __DEFAULT -> GHC.Prim.+# ww2 1# } -- RHS size: {terms: 15, types: 22, coercions: 1, joins: 0/0} @@ -219,7 +203,7 @@ i :: forall a. ExGADT a -> Int i = \ (@a) (ds :: ExGADT a) -> case ds of { ExGADT @e ww ww1 ww2 ww3 -> case ww3 of { GHC.Types.I# ww4 -> case T18982.$wi @a @e @~(ww :: a GHC.Prim.~# Int) ww2 ww4 of ww5 { __DEFAULT -> GHC.Types.I# ww5 } } } -- RHS size: {terms: 6, types: 7, coercions: 0, joins: 0/0} -T18982.$wh :: forall {a}. (a GHC.Prim.~# Int) => GHC.Prim.Int# -> GHC.Prim.Int# +T18982.$wh :: forall a. (a GHC.Prim.~# Int) => GHC.Prim.Int# -> GHC.Prim.Int# T18982.$wh = \ (@a) (ww :: a GHC.Prim.~# Int) (ww1 :: GHC.Prim.Int#) -> GHC.Prim.+# ww1 1# -- RHS size: {terms: 14, types: 15, coercions: 1, joins: 0/0} @@ -227,7 +211,7 @@ h :: forall a. GADT a -> Int h = \ (@a) (ds :: GADT a) -> case ds of { GADT ww ww1 -> case ww1 of { GHC.Types.I# ww2 -> case T18982.$wh @a @~(ww :: a GHC.Prim.~# Int) ww2 of ww3 { __DEFAULT -> GHC.Types.I# ww3 } } } -- RHS size: {terms: 9, types: 4, coercions: 0, joins: 0/0} -T18982.$wg :: forall {e}. e -> GHC.Prim.Int# -> GHC.Prim.Int# +T18982.$wg :: forall e. e -> GHC.Prim.Int# -> GHC.Prim.Int# T18982.$wg = \ (@e) (ww :: e) (ww1 :: GHC.Prim.Int#) -> case ww of { __DEFAULT -> GHC.Prim.+# ww1 1# } -- RHS size: {terms: 14, types: 11, coercions: 0, joins: 0/0} diff --git a/testsuite/tests/stranal/should_compile/T23398.stderr b/testsuite/tests/stranal/should_compile/T23398.stderr index 84177a1424f2a650923a5a89150477e5021eda14..03a7dbb9fd0c62b26f6217c59af7f57b05ad6e28 100644 --- a/testsuite/tests/stranal/should_compile/T23398.stderr +++ b/testsuite/tests/stranal/should_compile/T23398.stderr @@ -5,7 +5,7 @@ Result size of Tidy Core -- RHS size: {terms: 18, types: 11, coercions: 0, joins: 0/0} T23398.$wfoo [InlPrag=[2]] - :: forall {a}. (Eq a, Show a) => a -> a -> String + :: forall a. (Eq a, Show a) => a -> a -> String [GblId[StrictWorker([!, !])], Arity=4, Str=<SP(1C(1,C(1,L)),A)><SP(A,1C(1,L),A)><L><L>, @@ -41,7 +41,7 @@ foo Rec { -- RHS size: {terms: 21, types: 19, coercions: 3, joins: 0/0} T23398.$wbar [InlPrag=[2], Occ=LoopBreaker] - :: forall {a} {b}. + :: forall a b. (a GHC.Prim.~# b, Show a) => GHC.Prim.Int# -> a -> (# b, String #) [GblId[StrictWorker([~, !])], diff --git a/testsuite/tests/typecheck/should_compile/CoerceToVDQ.hs b/testsuite/tests/typecheck/should_compile/CoerceToVDQ.hs new file mode 100644 index 0000000000000000000000000000000000000000..0305683a596a9f7cc460e0e4988c7f3f0d5ff8c2 --- /dev/null +++ b/testsuite/tests/typecheck/should_compile/CoerceToVDQ.hs @@ -0,0 +1,27 @@ +{-# LANGUAGE ImpredicativeTypes, TypeFamilies, UndecidableInstances #-} +module CoerceToVDQ where + +import Data.Kind +import GHC.Exts (UnliftedType) + +import Data.Coerce + +type S0 = forall (k :: Type) -> k -> k + +type family S where + -- S just smuggles S0 past the validity checks + -- that normally prevent VDQ in types of terms + S = ArgKind (S0Consumer S0Inhabitant) + +type ArgKind :: Type -> Type +type family ArgKind a where + ArgKind (_ (arg :: k)) = k + +type S0Inhabitant :: S0 +data family S0Inhabitant a b + +type S0Consumer :: S0 -> Type +newtype S0Consumer f = Con (f Type Bool) + +test :: S +test = coerce @(forall t. t -> t) id diff --git a/testsuite/tests/typecheck/should_compile/T22537.hs b/testsuite/tests/typecheck/should_compile/T22537.hs new file mode 100644 index 0000000000000000000000000000000000000000..8bb892c4558f7412ac4d47c8ad3f5037a33c859d --- /dev/null +++ b/testsuite/tests/typecheck/should_compile/T22537.hs @@ -0,0 +1,15 @@ +{-# LANGUAGE ExplicitForAll #-} + +module T22537 where + +import Data.Coerce + +newtype M = MkM (forall a b. a -> b -> b) +newtype N a = MkN (forall b. a -> b -> b) +newtype P = MkP (forall a. N a) + +g1 :: M -> P +g1 x = coerce x + +g2 :: P -> M +g2 x = coerce x diff --git a/testsuite/tests/typecheck/should_compile/T22762.hs b/testsuite/tests/typecheck/should_compile/T22762.hs new file mode 100644 index 0000000000000000000000000000000000000000..2c343fde4b128e749aad24b25cfa4099ac44e9c0 --- /dev/null +++ b/testsuite/tests/typecheck/should_compile/T22762.hs @@ -0,0 +1,21 @@ +{-# LANGUAGE GHC2021 #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} +module Bug where + +import Data.Kind + +type Const :: a -> b -> a +type family Const x y where + Const x _ = x + +type F :: (forall (b :: Bool) -> Const Type b) -> Type +data F f + +type G :: forall (b :: Bool) -> Type +data G b + +type H :: Type +type family H where + H = F G diff --git a/testsuite/tests/typecheck/should_compile/all.T b/testsuite/tests/typecheck/should_compile/all.T index 13bb8cbd501c445e0de3263b4416e0749e9c3e75..edcc812181e52932717c819eb682f6c1a654657b 100644 --- a/testsuite/tests/typecheck/should_compile/all.T +++ b/testsuite/tests/typecheck/should_compile/all.T @@ -871,6 +871,8 @@ test('T22194', normal, compile, ['']) test('QualifiedRecordUpdate', [ extra_files(['QualifiedRecordUpdate_aux.hs']) ] , multimod_compile, ['QualifiedRecordUpdate', '-v0']) +test('CoerceToVDQ', normal, compile, ['-dlint']) +test('T22762', normal, compile, ['-dlint']) test('T23171', normal, compile, ['']) test('T23192', normal, compile, ['']) test('T23199', normal, compile, ['']) @@ -883,3 +885,5 @@ test('T22560d', extra_files(['T22560d.hs']), ghci_script, ['T22560d.script']) test('T22560e', normal, compile, ['']) test('T23514b', normal, compile, ['']) test('T23514c', normal, compile, ['']) +test('T22537', normal, compile, ['']) +