Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
fa5d33de
by Simon Peyton Jones at 2025-11-05T08:35:40-05:00
-
ea58cae5
by Simon Peyton Jones at 2025-11-05T08:35:40-05:00
17 changed files:
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Utils/Concrete.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/Type.hs
- + testsuite/tests/simplCore/should_compile/T26349.hs
- + testsuite/tests/simplCore/should_compile/T26349.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/simplCore/should_compile/rule2.stderr
Changes:
| ... | ... | @@ -41,7 +41,8 @@ module GHC.Core.Coercion ( |
| 41 | 41 | mkInstCo, mkAppCo, mkAppCos, mkTyConAppCo,
|
| 42 | 42 | mkFunCo, mkFunCo2, mkFunCoNoFTF, mkFunResCo,
|
| 43 | 43 | mkNakedFunCo,
|
| 44 | - mkNakedForAllCo, mkForAllCo, mkForAllVisCos, mkHomoForAllCos,
|
|
| 44 | + mkNakedForAllCo, mkForAllCo, mkForAllVisCos,
|
|
| 45 | + mkHomoForAllCo, mkHomoForAllCos,
|
|
| 45 | 46 | mkPhantomCo, mkAxiomCo,
|
| 46 | 47 | mkHoleCo, mkUnivCo, mkSubCo,
|
| 47 | 48 | mkProofIrrelCo,
|
| ... | ... | @@ -980,7 +981,7 @@ mkForAllCo v visL visR kind_co co |
| 980 | 981 | = mkReflCo r (mkTyCoForAllTy v visL ty)
|
| 981 | 982 | |
| 982 | 983 | | otherwise
|
| 983 | - = mkForAllCo_NoRefl v visL visR kind_co co
|
|
| 984 | + = mk_forall_co v visL visR kind_co co
|
|
| 984 | 985 | |
| 985 | 986 | -- mkForAllVisCos [tv{vis}] constructs a cast
|
| 986 | 987 | -- forall tv. res ~R# forall tv{vis} res`.
|
| ... | ... | @@ -1000,14 +1001,26 @@ mkHomoForAllCos vs orig_co |
| 1000 | 1001 | = foldr go orig_co vs
|
| 1001 | 1002 | where
|
| 1002 | 1003 | go :: ForAllTyBinder -> Coercion -> Coercion
|
| 1003 | - go (Bndr var vis) = mkForAllCo_NoRefl var vis vis MRefl
|
|
| 1004 | - |
|
| 1005 | --- | Like 'mkForAllCo', but there is no need to check that the inner coercion isn't Refl;
|
|
| 1006 | --- the caller has done that. (For example, it is guaranteed in 'mkHomoForAllCos'.)
|
|
| 1007 | --- The kind of the tycovar should be the left-hand kind of the kind coercion.
|
|
| 1008 | -mkForAllCo_NoRefl :: TyCoVar -> ForAllTyFlag -> ForAllTyFlag
|
|
| 1009 | - -> KindMCoercion -> Coercion -> Coercion
|
|
| 1010 | -mkForAllCo_NoRefl tcv visL visR kind_co co
|
|
| 1004 | + go (Bndr var vis) co = mk_forall_co var vis vis MRefl co
|
|
| 1005 | + |
|
| 1006 | +mkHomoForAllCo :: TyVar -> Coercion -> Coercion
|
|
| 1007 | +-- Specialised for a single TyVar,
|
|
| 1008 | +-- and visibility of coreTyLamForAllTyFlag
|
|
| 1009 | +mkHomoForAllCo tv orig_co
|
|
| 1010 | + | Just (ty, r) <- isReflCo_maybe orig_co
|
|
| 1011 | + = mkReflCo r (mkForAllTy (Bndr tv vis) ty)
|
|
| 1012 | + | otherwise
|
|
| 1013 | + = mk_forall_co tv vis vis MRefl orig_co
|
|
| 1014 | + where
|
|
| 1015 | + vis = coreTyLamForAllTyFlag
|
|
| 1016 | + |
|
| 1017 | +-- | `mk_forall_co` just builds a ForAllCo.
|
|
| 1018 | +-- With debug on, it checks invariants (e.g. he kind of the tycovar should
|
|
| 1019 | +-- be the left-hand kind of the kind coercion).
|
|
| 1020 | +-- Callers should have done any isReflCo short-cutting.
|
|
| 1021 | +mk_forall_co :: TyCoVar -> ForAllTyFlag -> ForAllTyFlag
|
|
| 1022 | + -> KindMCoercion -> Coercion -> Coercion
|
|
| 1023 | +mk_forall_co tcv visL visR kind_co co
|
|
| 1011 | 1024 | = assertGoodForAllCo tcv visL visR kind_co co $
|
| 1012 | 1025 | assertPpr (not (isReflCo co && isReflMCo kind_co && visL == visR)) (ppr co) $
|
| 1013 | 1026 | ForAllCo { fco_tcv = tcv, fco_visL = visL, fco_visR = visR
|
| ... | ... | @@ -1769,7 +1782,7 @@ mkPiCos r vs co = foldr (mkPiCo r) co vs |
| 1769 | 1782 | -- | Make a forall 'Coercion', where both types related by the coercion
|
| 1770 | 1783 | -- are quantified over the same variable.
|
| 1771 | 1784 | mkPiCo :: Role -> Var -> Coercion -> Coercion
|
| 1772 | -mkPiCo r v co | isTyVar v = mkHomoForAllCos [Bndr v coreTyLamForAllTyFlag] co
|
|
| 1785 | +mkPiCo r v co | isTyVar v = mkHomoForAllCo v co
|
|
| 1773 | 1786 | | isCoVar v = assert (not (v `elemVarSet` tyCoVarsOfCo co)) $
|
| 1774 | 1787 | -- We didn't call mkForAllCo here because if v does not appear
|
| 1775 | 1788 | -- in co, the argument coercion will be nominal. But here we
|
| ... | ... | @@ -187,11 +187,13 @@ liftPRType :: (Type -> Type) -> PRType -> PRType |
| 187 | 187 | liftPRType f pty = (f (prTypeType pty), [])
|
| 188 | 188 | |
| 189 | 189 | hsWrapperType :: HsWrapper -> Type -> Type
|
| 190 | +-- Return the type of (WrapExpr wrap e), given that e :: ty
|
|
| 190 | 191 | hsWrapperType wrap ty = prTypeType $ go wrap (ty,[])
|
| 191 | 192 | where
|
| 192 | 193 | go WpHole = id
|
| 194 | + go (WpSubType w) = go w
|
|
| 193 | 195 | go (w1 `WpCompose` w2) = go w1 . go w2
|
| 194 | - go (WpFun _ w2 (Scaled m exp_arg)) = liftPRType $ \t ->
|
|
| 196 | + go (WpFun _ w2 (Scaled m exp_arg) _) = liftPRType $ \t ->
|
|
| 195 | 197 | let act_res = funResultTy t
|
| 196 | 198 | exp_res = hsWrapperType w2 act_res
|
| 197 | 199 | in mkFunctionType m exp_arg exp_res
|
| ... | ... | @@ -1597,9 +1597,13 @@ dsHsWrapper hs_wrap thing_inside |
| 1597 | 1597 | ds_hs_wrapper :: HsWrapper
|
| 1598 | 1598 | -> ((CoreExpr -> CoreExpr) -> DsM a)
|
| 1599 | 1599 | -> DsM a
|
| 1600 | -ds_hs_wrapper wrap = go wrap
|
|
| 1600 | +ds_hs_wrapper hs_wrap
|
|
| 1601 | + = go hs_wrap
|
|
| 1601 | 1602 | where
|
| 1602 | 1603 | go WpHole k = k $ \e -> e
|
| 1604 | + go (WpSubType w) k = go (optSubTypeHsWrapper w) k
|
|
| 1605 | + -- See (DSST3) in Note [Deep subsumption and WpSubType]
|
|
| 1606 | + -- in GHC.Tc.Types.Evidence
|
|
| 1603 | 1607 | go (WpTyApp ty) k = k $ \e -> App e (Type ty)
|
| 1604 | 1608 | go (WpEvLam ev) k = k $ Lam ev
|
| 1605 | 1609 | go (WpTyLam tv) k = k $ Lam tv
|
| ... | ... | @@ -1612,13 +1616,13 @@ ds_hs_wrapper wrap = go wrap |
| 1612 | 1616 | go (WpCompose c1 c2) k = go c1 $ \w1 ->
|
| 1613 | 1617 | go c2 $ \w2 ->
|
| 1614 | 1618 | k (w1 . w2)
|
| 1615 | - go (WpFun c1 c2 st) k = -- See Note [Desugaring WpFun]
|
|
| 1616 | - do { x <- newSysLocalDs st
|
|
| 1617 | - ; go c1 $ \w1 ->
|
|
| 1618 | - go c2 $ \w2 ->
|
|
| 1619 | - let app f a = mkCoreApp (text "dsHsWrapper") f a
|
|
| 1620 | - arg = w1 (Var x)
|
|
| 1621 | - in k (\e -> (Lam x (w2 (app e arg)))) }
|
|
| 1619 | + go (WpFun c1 c2 st _) k = -- See Note [Desugaring WpFun]
|
|
| 1620 | + do { x <- newSysLocalDs st
|
|
| 1621 | + ; go c1 $ \w1 ->
|
|
| 1622 | + go c2 $ \w2 ->
|
|
| 1623 | + let app f a = mkCoreApp (text "dsHsWrapper") f a
|
|
| 1624 | + arg = w1 (Var x)
|
|
| 1625 | + in k (\e -> (Lam x (w2 (app e arg)))) }
|
|
| 1622 | 1626 | |
| 1623 | 1627 | --------------------------------------
|
| 1624 | 1628 | dsTcEvBinds_s :: [TcEvBinds] -> ([CoreBind] -> DsM a) -> DsM a
|
| ... | ... | @@ -1240,7 +1240,7 @@ viewLExprEq (e1,_) (e2,_) = lexp e1 e2 |
| 1240 | 1240 | -- equating different ways of writing a coercion)
|
| 1241 | 1241 | wrap WpHole WpHole = True
|
| 1242 | 1242 | wrap (WpCompose w1 w2) (WpCompose w1' w2') = wrap w1 w1' && wrap w2 w2'
|
| 1243 | - wrap (WpFun w1 w2 _) (WpFun w1' w2' _) = wrap w1 w1' && wrap w2 w2'
|
|
| 1243 | + wrap (WpFun w1 w2 _ _) (WpFun w1' w2' _ _) = wrap w1 w1' && wrap w2 w2'
|
|
| 1244 | 1244 | wrap (WpCast co) (WpCast co') = co `eqCoercion` co'
|
| 1245 | 1245 | wrap (WpEvApp et1) (WpEvApp et2) = et1 `ev_term` et2
|
| 1246 | 1246 | wrap (WpTyApp t) (WpTyApp t') = eqType t t'
|
| ... | ... | @@ -696,7 +696,7 @@ instance ToHie (LocatedA HsWrapper) where |
| 696 | 696 | (WpLet bs) -> toHie $ EvBindContext (mkScope osp) (getRealSpanA osp) (L osp bs)
|
| 697 | 697 | (WpCompose a b) -> concatM $
|
| 698 | 698 | [toHie (L osp a), toHie (L osp b)]
|
| 699 | - (WpFun a b _) -> concatM $
|
|
| 699 | + (WpFun a b _ _) -> concatM $
|
|
| 700 | 700 | [toHie (L osp a), toHie (L osp b)]
|
| 701 | 701 | (WpEvLam a) ->
|
| 702 | 702 | toHie $ C (EvidenceVarBind EvWrapperBind (mkScope osp) (getRealSpanA osp))
|
| ... | ... | @@ -823,9 +823,11 @@ tcFilterHoleFits limit typed_hole ht@(hole_ty, _) candidates = |
| 823 | 823 | |
| 824 | 824 | unfoldWrapper :: HsWrapper -> [Type]
|
| 825 | 825 | unfoldWrapper = reverse . unfWrp'
|
| 826 | - where unfWrp' (WpTyApp ty) = [ty]
|
|
| 827 | - unfWrp' (WpCompose w1 w2) = unfWrp' w1 ++ unfWrp' w2
|
|
| 828 | - unfWrp' _ = []
|
|
| 826 | + where
|
|
| 827 | + unfWrp' (WpTyApp ty) = [ty]
|
|
| 828 | + unfWrp' (WpSubType w) = unfWrp' w
|
|
| 829 | + unfWrp' (WpCompose w1 w2) = unfWrp' w1 ++ unfWrp' w2
|
|
| 830 | + unfWrp' _ = []
|
|
| 829 | 831 | |
| 830 | 832 | |
| 831 | 833 | -- The real work happens here, where we invoke the type checker using
|
| ... | ... | @@ -794,7 +794,7 @@ tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args |
| 794 | 794 | = do { let herald = case fun_ctxt of
|
| 795 | 795 | VAExpansion (OrigStmt{}) _ _ -> ExpectedFunTySyntaxOp DoOrigin tc_fun
|
| 796 | 796 | _ -> ExpectedFunTyArg (HsExprTcThing tc_fun) (unLoc arg)
|
| 797 | - ; (wrap, arg_ty, res_ty) <-
|
|
| 797 | + ; (fun_co, arg_ty, res_ty) <-
|
|
| 798 | 798 | -- NB: matchActualFunTy does the rep-poly check.
|
| 799 | 799 | -- For example, suppose we have f :: forall r (a::TYPE r). a -> Int
|
| 800 | 800 | -- In an application (f x), we need 'x' to have a fixed runtime
|
| ... | ... | @@ -805,7 +805,7 @@ tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args |
| 805 | 805 | (n_val_args, fun_sigma) fun_ty
|
| 806 | 806 | |
| 807 | 807 | ; arg' <- quickLookArg do_ql ctxt arg arg_ty
|
| 808 | - ; let acc' = arg' : addArgWrap wrap acc
|
|
| 808 | + ; let acc' = arg' : addArgWrap (mkWpCastN fun_co) acc
|
|
| 809 | 809 | ; go (pos+1) acc' res_ty rest_args }
|
| 810 | 810 | |
| 811 | 811 | new_arg_ty :: LHsExpr GhcRn -> Int -> TcM (Scaled TcType)
|
| ... | ... | @@ -765,13 +765,13 @@ tcInferOverLit lit@(OverLit { ol_val = val |
| 765 | 765 | thing = NameThing from_name
|
| 766 | 766 | mb_thing = Just thing
|
| 767 | 767 | herald = ExpectedFunTyArg thing (HsLit noExtField hs_lit)
|
| 768 | - ; (wrap2, sarg_ty, res_ty) <- matchActualFunTy herald mb_thing (1, from_ty) from_ty
|
|
| 768 | + ; (co2, sarg_ty, res_ty) <- matchActualFunTy herald mb_thing (1, from_ty) from_ty
|
|
| 769 | 769 | |
| 770 | 770 | ; co <- unifyType mb_thing (hsLitType hs_lit) (scaledThing sarg_ty)
|
| 771 | 771 | -- See Note [Source locations for implicit function calls] in GHC.Iface.Ext.Ast
|
| 772 | 772 | ; let lit_expr = L (l2l loc) $ mkHsWrapCo co $
|
| 773 | 773 | HsLit noExtField hs_lit
|
| 774 | - from_expr = mkHsWrap (wrap2 <.> wrap1) $
|
|
| 774 | + from_expr = mkHsWrap (mkWpCastN co2 <.> wrap1) $
|
|
| 775 | 775 | mkHsVar (L loc from_id)
|
| 776 | 776 | witness = HsApp noExtField (L (l2l loc) from_expr) lit_expr
|
| 777 | 777 | lit' = OverLit { ol_val = val
|
| ... | ... | @@ -699,7 +699,7 @@ tc_pat pat_ty penv ps_pat thing_inside = case ps_pat of |
| 699 | 699 | |
| 700 | 700 | -- Expression must be a function
|
| 701 | 701 | ; let herald = ExpectedFunTyViewPat $ unLoc expr
|
| 702 | - ; (expr_wrap1, Scaled _mult inf_arg_ty, inf_res_sigma)
|
|
| 702 | + ; (expr_co1, Scaled _mult inf_arg_ty, inf_res_sigma)
|
|
| 703 | 703 | <- matchActualFunTy herald (Just . HsExprRnThing $ unLoc expr) (1,expr_rho) expr_rho
|
| 704 | 704 | -- See Note [View patterns and polymorphism]
|
| 705 | 705 | -- expr_wrap1 :: expr_rho "->" (inf_arg_ty -> inf_res_sigma)
|
| ... | ... | @@ -720,7 +720,7 @@ tc_pat pat_ty penv ps_pat thing_inside = case ps_pat of |
| 720 | 720 | -- NB: pat_ty comes from matchActualFunTy, so it has a
|
| 721 | 721 | -- fixed RuntimeRep, as needed to call mkWpFun.
|
| 722 | 722 | |
| 723 | - expr_wrap = expr_wrap2' <.> expr_wrap1
|
|
| 723 | + expr_wrap = expr_wrap2' <.> mkWpCastN expr_co1
|
|
| 724 | 724 | |
| 725 | 725 | ; return $ (ViewPat pat_ty (mkLHsWrap expr_wrap expr') pat', res) }
|
| 726 | 726 |
| ... | ... | @@ -8,10 +8,11 @@ module GHC.Tc.Types.Evidence ( |
| 8 | 8 | -- * HsWrapper
|
| 9 | 9 | HsWrapper(..),
|
| 10 | 10 | (<.>), mkWpTyApps, mkWpEvApps, mkWpEvVarApps, mkWpTyLams, mkWpForAllCast,
|
| 11 | - mkWpEvLams, mkWpLet, mkWpFun, mkWpCastN, mkWpCastR, mkWpEta,
|
|
| 11 | + mkWpEvLams, mkWpLet, mkWpFun, mkWpCastN, mkWpCastR, mkWpEta, mkWpSubType,
|
|
| 12 | 12 | collectHsWrapBinders,
|
| 13 | 13 | idHsWrapper, isIdHsWrapper,
|
| 14 | 14 | pprHsWrapper, hsWrapDictBinders,
|
| 15 | + optSubTypeHsWrapper,
|
|
| 15 | 16 | |
| 16 | 17 | -- * Evidence bindings
|
| 17 | 18 | TcEvBinds(..), EvBindsVar(..),
|
| ... | ... | @@ -73,7 +74,7 @@ import GHC.Types.Unique.DFM |
| 73 | 74 | import GHC.Types.Unique.FM
|
| 74 | 75 | import GHC.Types.Name( isInternalName )
|
| 75 | 76 | import GHC.Types.Var
|
| 76 | -import GHC.Types.Id( idScaledType )
|
|
| 77 | +import GHC.Types.Id( idScaledType, idType )
|
|
| 77 | 78 | import GHC.Types.Var.Env
|
| 78 | 79 | import GHC.Types.Var.Set
|
| 79 | 80 | import GHC.Types.Basic
|
| ... | ... | @@ -134,35 +135,128 @@ maybeSymCo NotSwapped co = co |
| 134 | 135 | ************************************************************************
|
| 135 | 136 | -}
|
| 136 | 137 | |
| 137 | --- We write wrap :: t1 ~> t2
|
|
| 138 | --- if wrap[ e::t1 ] :: t2
|
|
| 138 | +{- Note [Deep subsumption and WpSubType]
|
|
| 139 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 140 | +When making DeepSubsumption checks, we may end up with hard-to-spot identity wrappers.
|
|
| 141 | +For example (#26349) suppose we have
|
|
| 142 | + (forall a. Eq a => a->a) -> Int <= (forall a. Eq a => a->a) -> Int
|
|
| 143 | +The two types are equal so we should certainly get an identity wrapper. But we'll get
|
|
| 144 | +tihs wrapper from `tcSubType`:
|
|
| 145 | + WpFun (WpTyLam a <.> WpEvLam dg <.> WpLet (dw=dg) <.> WpEvApp dw <.> WpTyApp a)
|
|
| 146 | + WpHole
|
|
| 147 | +That elaborate wrapper is really just a no-op, but it's far from obvious. If we just
|
|
| 148 | +desugar (HsWrap f wp) straightforwardly we'll get
|
|
| 149 | + \(g:forall a. Eq a => a -> a).
|
|
| 150 | + f (/\a. \(dg:Eq a). let dw=dg in g a dw)
|
|
| 151 | + |
|
| 152 | +To recognise that as just `f`, we'd have to eta-reduce twice. But eta-reduction
|
|
| 153 | +is not sound in general, so we'll end up retaining the lambdas. Two bad results:
|
|
| 154 | + |
|
| 155 | +* Adding DeepSubsumption gratuitiously makes programs less efficient.
|
|
| 156 | + |
|
| 157 | +* When the subsumption is on the LHS of a rule, or in a SPECIALISE pragma, we
|
|
| 158 | + may not be able to make a decent RULE at all, and will fail with "LHS of rule
|
|
| 159 | + is too complicated to desugar" (#26255)
|
|
| 160 | + |
|
| 161 | +It'd be ideal to solve the problem at the source, by never generating those
|
|
| 162 | +gruesome wrappers in the first place, but we can't do that because:
|
|
| 163 | + |
|
| 164 | +* The WpTyLam and WpTyApp are introduced independently, not together, in `tcSubType`,
|
|
| 165 | + so we can't easily cancel them out. For example, even if we have
|
|
| 166 | + forall a. t1 <= forall a. t2
|
|
| 167 | + there is no guarantee that these are the "same" a. E.g.
|
|
| 168 | + forall a b. a -> b -> b <= forall x y. y -> x -> x
|
|
| 169 | + Similarly WpEvLam and WpEvApp
|
|
| 170 | + |
|
| 171 | +* We have not yet done constraint solving so we don't know what evidence will
|
|
| 172 | + end up in those WpLet bindings.
|
|
| 173 | + |
|
| 174 | +TL;DR we must generate the wrapper and then optimise it way if it turns out
|
|
| 175 | +that it is a no-op. Here's our solution:
|
|
| 176 | + |
|
| 177 | +(DSST1) Tag the wrappers generated from a subtype check with WpSubType. In normal
|
|
| 178 | + wrappers the binders of a WpTyLam or WpEvLam can scope over the "hole" of the
|
|
| 179 | + wrapper -- that is how we introduce type-lambdas and dictionary-lambda into the
|
|
| 180 | + terms! But in /subtype/ wrappers, these type/dictionary lambdas only scope over
|
|
| 181 | + the WpTyApp and WpEvApp nodes in the /same/ wrapper. That is what justifies us
|
|
| 182 | + eta-reducing the type/dictionary lambdas.
|
|
| 183 | + |
|
| 184 | + In short, (WpSubType wp) means the same as `wp`, but with the added promise that
|
|
| 185 | + the binders in `wp` do not scope over the hole.
|
|
| 186 | + |
|
| 187 | +(DSST2) Avoid creating a WpSubType in the common WpHole case, using `mkWpSubType`.
|
|
| 188 | + |
|
| 189 | +(DSST3) When desugaring, try eta-reduction on the payload of a WpSubType.
|
|
| 190 | + This is done in `GHC.HsToCore.Binds.dsHsWrapper` by the call to `optSubTypeHsWrapper`.
|
|
| 191 | + |
|
| 192 | + We don't attempt to optimise HsWrappers /other than/ subtype wrappers. Why not?
|
|
| 193 | + Because there aren't any useful optimsations we can do. (We could collapse
|
|
| 194 | + adjacent `WpCast`s perhaps, but that'll happen later automatically via `mkCast`.)
|
|
| 195 | + |
|
| 196 | + TL;DR:
|
|
| 197 | + * we /must/ optimise subtype-HsWrappers (that's the point of this Note!)
|
|
| 198 | + * there is little point in attempting to optimise any other HsWrappers
|
|
| 199 | + |
|
| 200 | +Note [WpFun-RR-INVARIANT]
|
|
| 201 | +~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 202 | +Given
|
|
| 203 | + wrap = WpFun wrap1 wrap2 sty1 ty2
|
|
| 204 | + where: wrap1 :: exp_arg ~~> act_arg
|
|
| 205 | + wrap2 :: act_res ~~> exp_res
|
|
| 206 | + wrap :: (act_arg -> act_res) ~~> (exp_arg -> exp_res)
|
|
| 207 | +we have
|
|
| 208 | + WpFun-RR-INVARIANT:
|
|
| 209 | + the input (exp_arg) and output (act_arg) types of `wrap1`
|
|
| 210 | + both have a fixed runtime-rep
|
|
| 211 | + |
|
| 212 | +Reason: We desugar wrap[e] into
|
|
| 213 | + \(x:exp_arg). wrap2[ e wrap1[x] ]
|
|
| 214 | +And then, because of Note [Representation polymorphism invariants], we need:
|
|
| 215 | + |
|
| 216 | + * `exp_arg` must have a fixed runtime rep,
|
|
| 217 | + so that lambda obeys the the FRR rules
|
|
| 218 | + |
|
| 219 | + * `act_arg` must have a fixed runtime rep,
|
|
| 220 | + so the that application (e wrap1[x]) obeys the FRR tules
|
|
| 221 | + |
|
| 222 | +Hence WpFun-INVARIANT.
|
|
| 223 | +-}
|
|
| 224 | + |
|
| 139 | 225 | data HsWrapper
|
| 226 | + -- NOTATION (~~>):
|
|
| 227 | + -- We write wrap :: t1 ~~> t2
|
|
| 228 | + -- if wrap[ e::t1 ] :: t2
|
|
| 140 | 229 | = WpHole -- The identity coercion
|
| 141 | 230 | |
| 231 | + | WpSubType HsWrapper
|
|
| 232 | + -- (WpSubType wp) is the same as `wp`, but with extra invariants
|
|
| 233 | + -- See Note [Deep subsumption and WpSubType] (DSST1)
|
|
| 234 | + |
|
| 142 | 235 | | WpCompose HsWrapper HsWrapper
|
| 143 | 236 | -- (wrap1 `WpCompose` wrap2)[e] = wrap1[ wrap2[ e ]]
|
| 144 | 237 | --
|
| 145 | 238 | -- Hence (\a. []) `WpCompose` (\b. []) = (\a b. [])
|
| 146 | 239 | -- But ([] a) `WpCompose` ([] b) = ([] b a)
|
| 147 | 240 | --
|
| 148 | - -- If wrap1 :: t2 ~> t3
|
|
| 149 | - -- wrap2 :: t1 ~> t2
|
|
| 150 | - --- Then (wrap1 `WpCompose` wrap2) :: t1 ~> t3
|
|
| 151 | - |
|
| 152 | - | WpFun HsWrapper HsWrapper (Scaled TcTypeFRR)
|
|
| 153 | - -- (WpFun wrap1 wrap2 (w, t1))[e] = \(x:_w exp_arg). wrap2[ e wrap1[x] ]
|
|
| 154 | - -- So note that if e :: act_arg -> act_res
|
|
| 155 | - -- wrap1 :: exp_arg ~> act_arg
|
|
| 156 | - -- wrap2 :: act_res ~> exp_res
|
|
| 157 | - -- then WpFun wrap1 wrap2 : (act_arg -> arg_res) ~> (exp_arg -> exp_res)
|
|
| 241 | + -- If wrap1 :: t2 ~~> t3
|
|
| 242 | + -- wrap2 :: t1 ~~> t2
|
|
| 243 | + --- Then (wrap1 `WpCompose` wrap2) :: t1 ~~> t3
|
|
| 244 | + |
|
| 245 | + | WpFun HsWrapper HsWrapper (Scaled TcTypeFRR) TcType
|
|
| 246 | + -- (WpFun wrap1 wrap2 (w, t1) t2)[e] = \(x:_w exp_arg). wrap2[ e wrap1[x] ]
|
|
| 247 | + --
|
|
| 248 | + -- INVARIANT: both input and output types of `wrap1` have a fixed runtime-rep
|
|
| 249 | + -- See Note [WpFun-RR-INVARIANT]
|
|
| 250 | + --
|
|
| 251 | + -- Typing rules:
|
|
| 252 | + -- If e :: act_arg -> act_res
|
|
| 253 | + -- wrap1 :: exp_arg ~~> act_arg
|
|
| 254 | + -- wrap2 :: act_res ~~> exp_res
|
|
| 255 | + -- then WpFun wrap1 wrap2 :: (act_arg -> act_res) ~~> (exp_arg -> exp_res)
|
|
| 158 | 256 | -- This isn't the same as for mkFunCo, but it has to be this way
|
| 159 | 257 | -- because we can't use 'sym' to flip around these HsWrappers
|
| 160 | - -- The TcType is the "from" type of the first wrapper;
|
|
| 161 | - -- it always a Type, not a Constraint
|
|
| 162 | 258 | --
|
| 163 | - -- NB: a WpFun is always for a (->) function arrow
|
|
| 164 | - --
|
|
| 165 | - -- Use 'mkWpFun' to construct such a wrapper.
|
|
| 259 | + -- NB: a WpFun is always for a (->) function arrow, never (=>)
|
|
| 166 | 260 | |
| 167 | 261 | | WpCast TcCoercionR -- A cast: [] `cast` co
|
| 168 | 262 | -- Guaranteed not the identity coercion
|
| ... | ... | @@ -212,50 +306,48 @@ WpCast c1 <.> WpCast c2 = WpCast (c2 `mkTransCo` c1) |
| 212 | 306 | --
|
| 213 | 307 | -- NB: <.> behaves like function composition:
|
| 214 | 308 | --
|
| 215 | - -- WpCast c1 <.> WpCast c2 :: coercionLKind c2 ~> coercionRKind c1
|
|
| 309 | + -- WpCast c1 <.> WpCast c2 :: coercionLKind c2 ~~> coercionRKind c1
|
|
| 216 | 310 | --
|
| 217 | 311 | -- This is thus the same as WpCast (c2 ; c1) and not WpCast (c1 ; c2).
|
| 218 | 312 | c1 <.> c2 = c1 `WpCompose` c2
|
| 219 | 313 | |
| 220 | --- | Smart constructor to create a 'WpFun' 'HsWrapper', which avoids introducing
|
|
| 221 | --- a lambda abstraction if the two supplied wrappers are either identities or
|
|
| 222 | --- casts.
|
|
| 223 | ---
|
|
| 224 | --- PRECONDITION: either:
|
|
| 225 | ---
|
|
| 226 | --- 1. both of the 'HsWrapper's are identities or casts, or
|
|
| 227 | --- 2. both the "from" and "to" types of the first wrapper have a syntactically
|
|
| 228 | --- fixed RuntimeRep (see Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete).
|
|
| 229 | 314 | mkWpFun :: HsWrapper -> HsWrapper
|
| 230 | 315 | -> Scaled TcTypeFRR -- ^ the "from" type of the first wrapper
|
| 231 | 316 | -> TcType -- ^ Either "from" type or "to" type of the second wrapper
|
| 232 | 317 | -- (used only when the second wrapper is the identity)
|
| 233 | 318 | -> HsWrapper
|
| 234 | -mkWpFun WpHole WpHole _ _ = WpHole
|
|
| 235 | -mkWpFun WpHole (WpCast co2) (Scaled w t1) _ = WpCast (mk_wp_fun_co w (mkRepReflCo t1) co2)
|
|
| 236 | -mkWpFun (WpCast co1) WpHole (Scaled w _) t2 = WpCast (mk_wp_fun_co w (mkSymCo co1) (mkRepReflCo t2))
|
|
| 237 | -mkWpFun (WpCast co1) (WpCast co2) (Scaled w _) _ = WpCast (mk_wp_fun_co w (mkSymCo co1) co2)
|
|
| 238 | -mkWpFun w_arg w_res t1 _ =
|
|
| 239 | - -- In this case, we will desugar to a lambda
|
|
| 240 | - --
|
|
| 241 | - -- \x. w_res[ e w_arg[x] ]
|
|
| 242 | - --
|
|
| 243 | - -- To satisfy Note [Representation polymorphism invariants] in GHC.Core,
|
|
| 244 | - -- it must be the case that both the lambda bound variable x and the function
|
|
| 245 | - -- argument w_arg[x] have a fixed runtime representation, i.e. that both the
|
|
| 246 | - -- "from" and "to" types of the first wrapper "w_arg" have a fixed runtime representation.
|
|
| 247 | - --
|
|
| 248 | - -- Unfortunately, we can't check this with an assertion here, because of
|
|
| 249 | - -- [Wrinkle: Typed Template Haskell] in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.
|
|
| 250 | - WpFun w_arg w_res t1
|
|
| 251 | - |
|
| 252 | -mkWpEta :: [Id] -> HsWrapper -> HsWrapper
|
|
| 319 | +-- ^ Smart constructor for `WpFun`
|
|
| 320 | +-- Just removes clutter and optimises some common cases.
|
|
| 321 | +--
|
|
| 322 | +-- PRECONDITION: same as Note [WpFun-RR-INVARIANT]
|
|
| 323 | +--
|
|
| 324 | +-- Unfortunately, we can't check PRECONDITION with an assertion here, because of
|
|
| 325 | +-- [Wrinkle: Typed Template Haskell] in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.
|
|
| 326 | +mkWpFun w1 w2 st1@(Scaled m1 t1) t2
|
|
| 327 | + = case (w1,w2) of
|
|
| 328 | + (WpHole, WpHole) -> WpHole
|
|
| 329 | + (WpHole, WpCast co2) -> WpCast (mk_wp_fun_co m1 (mkRepReflCo t1) co2)
|
|
| 330 | + (WpCast co1, WpHole) -> WpCast (mk_wp_fun_co m1 (mkSymCo co1) (mkRepReflCo t2))
|
|
| 331 | + (WpCast co1, WpCast co2) -> WpCast (mk_wp_fun_co m1 (mkSymCo co1) co2)
|
|
| 332 | + (_, _) -> WpFun w1 w2 st1 t2
|
|
| 333 | + |
|
| 334 | +mkWpSubType :: HsWrapper -> HsWrapper
|
|
| 335 | +-- See (DSST2) in Note [Deep subsumption and WpSubType]
|
|
| 336 | +mkWpSubType WpHole = WpHole
|
|
| 337 | +mkWpSubType (WpCast co) = WpCast co
|
|
| 338 | +mkWpSubType w = WpSubType w
|
|
| 339 | + |
|
| 340 | +mkWpEta :: Type -> [Id] -> HsWrapper -> HsWrapper
|
|
| 253 | 341 | -- (mkWpEta [x1, x2] wrap) [e]
|
| 254 | 342 | -- = \x1. \x2. wrap[e x1 x2]
|
| 255 | 343 | -- Just generates a bunch of WpFuns
|
| 256 | -mkWpEta xs wrap = foldr eta_one wrap xs
|
|
| 344 | +-- The incoming type is the type of the entire expression
|
|
| 345 | +mkWpEta orig_fun_ty xs wrap = go orig_fun_ty xs
|
|
| 257 | 346 | where
|
| 258 | - eta_one x wrap = WpFun idHsWrapper wrap (idScaledType x)
|
|
| 347 | + go _ [] = wrap
|
|
| 348 | + go fun_ty (id:ids) = WpFun idHsWrapper (go res_ty ids) (idScaledType id) res_ty
|
|
| 349 | + where
|
|
| 350 | + res_ty = funResultTy fun_ty
|
|
| 259 | 351 | |
| 260 | 352 | mk_wp_fun_co :: Mult -> TcCoercionR -> TcCoercionR -> TcCoercionR
|
| 261 | 353 | mk_wp_fun_co mult arg_co res_co
|
| ... | ... | @@ -333,8 +425,9 @@ hsWrapDictBinders wrap = go wrap |
| 333 | 425 | where
|
| 334 | 426 | go (WpEvLam dict_id) = unitBag dict_id
|
| 335 | 427 | go (w1 `WpCompose` w2) = go w1 `unionBags` go w2
|
| 336 | - go (WpFun _ w _) = go w
|
|
| 428 | + go (WpFun _ w _ _) = go w
|
|
| 337 | 429 | go WpHole = emptyBag
|
| 430 | + go (WpSubType {}) = emptyBag -- See Note [Deep subsumption and WpSubType]
|
|
| 338 | 431 | go (WpCast {}) = emptyBag
|
| 339 | 432 | go (WpEvApp {}) = emptyBag
|
| 340 | 433 | go (WpTyLam {}) = emptyBag
|
| ... | ... | @@ -350,6 +443,7 @@ collectHsWrapBinders wrap = go wrap [] |
| 350 | 443 | go :: HsWrapper -> [HsWrapper] -> ([Var], HsWrapper)
|
| 351 | 444 | go (WpEvLam v) wraps = add_lam v (gos wraps)
|
| 352 | 445 | go (WpTyLam v) wraps = add_lam v (gos wraps)
|
| 446 | + go (WpSubType w) wraps = go w wraps
|
|
| 353 | 447 | go (WpCompose w1 w2) wraps = go w1 (w2:wraps)
|
| 354 | 448 | go wrap wraps = ([], foldl' (<.>) wrap wraps)
|
| 355 | 449 | |
| ... | ... | @@ -358,6 +452,162 @@ collectHsWrapBinders wrap = go wrap [] |
| 358 | 452 | |
| 359 | 453 | add_lam v (vs,w) = (v:vs, w)
|
| 360 | 454 | |
| 455 | + |
|
| 456 | +optSubTypeHsWrapper :: HsWrapper -> HsWrapper
|
|
| 457 | +-- This optimiser is used only on the payload of WpSubType
|
|
| 458 | +-- It finds cases where the entire wrapper is a no-op
|
|
| 459 | +-- See (DSST3) in Note [Deep subsumption and WpSubType]
|
|
| 460 | +optSubTypeHsWrapper wrap
|
|
| 461 | + = opt wrap
|
|
| 462 | + where
|
|
| 463 | + opt :: HsWrapper -> HsWrapper
|
|
| 464 | + opt w = foldr (<.>) WpHole (opt1 w [])
|
|
| 465 | + |
|
| 466 | + opt1 :: HsWrapper -> [HsWrapper] -> [HsWrapper]
|
|
| 467 | + -- opt1 w ws = w <.> (foldr <.> WpHole ws)
|
|
| 468 | + -- INVARIANT: ws::[HsWrapper] is optimised
|
|
| 469 | + opt1 WpHole ws = ws
|
|
| 470 | + opt1 (WpSubType w) ws = opt1 w ws
|
|
| 471 | + opt1 (w1 `WpCompose` w2) ws = opt1 w1 (opt1 w2 ws)
|
|
| 472 | + opt1 (WpCast co) ws = opt_co co ws
|
|
| 473 | + opt1 (WpEvLam ev) ws = opt_ev_lam ev ws
|
|
| 474 | + opt1 (WpTyLam tv) ws = opt_ty_lam tv ws
|
|
| 475 | + opt1 (WpLet binds) ws = pushWpLet binds ws
|
|
| 476 | + opt1 (WpFun w1 w2 sty1 ty2) ws = opt_fun w1 w2 sty1 ty2 ws
|
|
| 477 | + opt1 w@(WpTyApp {}) ws = w : ws
|
|
| 478 | + opt1 w@(WpEvApp {}) ws = w : ws
|
|
| 479 | + |
|
| 480 | + -----------------
|
|
| 481 | + -- (WpTyLam a <.> WpTyApp a <.> w) = w
|
|
| 482 | + -- i.e. /\a. <hole> a --> <hole>
|
|
| 483 | + -- This is only valid if whatever fills the hole does not mention 'a'
|
|
| 484 | + -- But that's guaranteed in subtype-wrappers;
|
|
| 485 | + -- see (DSST1) in Note [Deep subsumption and WpSubType]
|
|
| 486 | + opt_ty_lam tv (WpTyApp ty : ws)
|
|
| 487 | + | Just tv' <- getTyVar_maybe ty
|
|
| 488 | + , tv==tv'
|
|
| 489 | + , all (tv `not_in`) ws
|
|
| 490 | + = ws
|
|
| 491 | + |
|
| 492 | + -- (WpTyLam a <.> WpCastCo co <.> w)
|
|
| 493 | + -- = WpCast (ForAllCo a co) (WpTyLam <.> w)
|
|
| 494 | + opt_ty_lam tv (WpCast co : ws)
|
|
| 495 | + = opt_co (mkHomoForAllCo tv co) (opt_ty_lam tv ws)
|
|
| 496 | + |
|
| 497 | + opt_ty_lam tv ws
|
|
| 498 | + = WpTyLam tv : ws
|
|
| 499 | + |
|
| 500 | + -----------------
|
|
| 501 | + -- (WpEvLam ev <.> WpEvAp ev <.> w) = w
|
|
| 502 | + -- Similar notes to WpTyLam
|
|
| 503 | + opt_ev_lam ev (WpEvApp ev_tm : ws)
|
|
| 504 | + | EvExpr (Var ev') <- ev_tm
|
|
| 505 | + , ev == ev'
|
|
| 506 | + , all (ev `not_in`) ws
|
|
| 507 | + = ws
|
|
| 508 | + |
|
| 509 | + -- (WpEvLam ev <.> WpCast co <.> w)
|
|
| 510 | + -- = WpCast (FunCo ev co) (WpEvLam <.> w)
|
|
| 511 | + opt_ev_lam ev (WpCast co : ws)
|
|
| 512 | + = opt_co fun_co (opt_ev_lam ev ws)
|
|
| 513 | + where
|
|
| 514 | + fun_co = mkFunCo Representational FTF_C_T
|
|
| 515 | + (mkNomReflCo ManyTy)
|
|
| 516 | + (mkRepReflCo (idType ev))
|
|
| 517 | + co
|
|
| 518 | + |
|
| 519 | + opt_ev_lam ev ws
|
|
| 520 | + = WpEvLam ev : ws
|
|
| 521 | + |
|
| 522 | + -----------------
|
|
| 523 | + -- WpCast co <.> WpCast co' <.> ws = WpCast (co;co') ws
|
|
| 524 | + opt_co co (WpCast co' : ws) = opt_co (co `mkTransCo` co') ws
|
|
| 525 | + opt_co co ws | isReflexiveCo co = ws
|
|
| 526 | + | otherwise = WpCast co : ws
|
|
| 527 | + |
|
| 528 | + ------------------
|
|
| 529 | + opt_fun w1 w2 sty1 ty2 ws
|
|
| 530 | + = case mkWpFun (opt w1) (opt w2) sty1 ty2 of
|
|
| 531 | + WpHole -> ws
|
|
| 532 | + WpCast co -> opt_co co ws
|
|
| 533 | + w -> w : ws
|
|
| 534 | + |
|
| 535 | + ------------------
|
|
| 536 | + -- Tiresome check that the lambda-bound type/evidence variable that we
|
|
| 537 | + -- want to eta-reduce isn't free in the rest of the wrapper
|
|
| 538 | + not_in :: TyVar -> HsWrapper -> Bool
|
|
| 539 | + not_in _ WpHole = True
|
|
| 540 | + not_in v (WpCast co) = not (anyFreeVarsOfCo (== v) co)
|
|
| 541 | + not_in v (WpTyApp ty) = not (anyFreeVarsOfType (== v) ty)
|
|
| 542 | + not_in v (WpFun w1 w2 _ _) = not_in v w1 && not_in v w2
|
|
| 543 | + not_in v (WpSubType w) = not_in v w
|
|
| 544 | + not_in v (WpCompose w1 w2) = not_in v w1 && not_in v w2
|
|
| 545 | + not_in v (WpEvApp (EvExpr e)) = not (v `elemVarSet` exprFreeVars e)
|
|
| 546 | + not_in _ (WpEvApp (EvTypeable {})) = False -- Giving up; conservative
|
|
| 547 | + not_in _ (WpEvApp (EvFun {})) = False -- Giving up; conservative
|
|
| 548 | + not_in _ (WpTyLam {}) = False -- Give up; conservative
|
|
| 549 | + not_in _ (WpEvLam {}) = False -- Ditto
|
|
| 550 | + not_in _ (WpLet {}) = False -- Ditto
|
|
| 551 | + |
|
| 552 | +pushWpLet :: TcEvBinds -> [HsWrapper] -> [HsWrapper]
|
|
| 553 | +-- See if we can transform
|
|
| 554 | +-- WpLet binds <.> w1 <.> .. <.> wn --> w1' <.> .. <.> wn'
|
|
| 555 | +-- by substitution.
|
|
| 556 | +-- We do this just for the narrow case when
|
|
| 557 | +-- - the `binds` are all just v=w, variables only
|
|
| 558 | +-- - the wi are all WpTyApp, WpEvApp, or WpCast
|
|
| 559 | +-- This is just enough to get us the eta-reductions that we seek
|
|
| 560 | +pushWpLet tc_ev_binds ws
|
|
| 561 | + = case tc_ev_binds of
|
|
| 562 | + TcEvBinds {} -> pprPanic "pushWpLet" (ppr tc_ev_binds)
|
|
| 563 | + EvBinds binds
|
|
| 564 | + | isEmptyBag binds
|
|
| 565 | + -> ws
|
|
| 566 | + | Just env <- ev_bind_swizzle binds
|
|
| 567 | + -> case go env ws of
|
|
| 568 | + Just ws' -> ws'
|
|
| 569 | + Nothing -> bale_out
|
|
| 570 | + | otherwise
|
|
| 571 | + -> bale_out
|
|
| 572 | + where
|
|
| 573 | + bale_out = WpLet tc_ev_binds : ws
|
|
| 574 | + |
|
| 575 | + go :: IdEnv Id -> [HsWrapper] -> Maybe [HsWrapper]
|
|
| 576 | + go env (WpCast co : ws) = do { ws' <- go env ws
|
|
| 577 | + ; return (WpCast co : ws') }
|
|
| 578 | + go env (WpTyApp ty : ws) = do { ws' <- go env ws
|
|
| 579 | + ; return (WpTyApp ty : ws') }
|
|
| 580 | + go env (WpEvApp (EvExpr (Var v)) : ws)
|
|
| 581 | + = do { v' <- swizzle_id env v
|
|
| 582 | + ; ws' <- go env ws
|
|
| 583 | + ; return (WpEvApp (EvExpr (Var v')) : ws') }
|
|
| 584 | + |
|
| 585 | + go _ ws = case ws of
|
|
| 586 | + [] -> Just []
|
|
| 587 | + (_:_) -> Nothing -- Could not fully eliminate the WpLet
|
|
| 588 | + |
|
| 589 | + swizzle_id :: IdEnv Id -> Id -> Maybe Id
|
|
| 590 | + -- Nothing <=> ran out of fuel
|
|
| 591 | + -- This is just belt and braces; we should never build bottom evidence
|
|
| 592 | + swizzle_id env v = go 100 v
|
|
| 593 | + where
|
|
| 594 | + go :: Int -> EvId -> Maybe EvId
|
|
| 595 | + go fuel v
|
|
| 596 | + | fuel == 0 = Nothing
|
|
| 597 | + | Just v' <- lookupVarEnv env v = go (fuel-1) v'
|
|
| 598 | + | otherwise = Just v
|
|
| 599 | + |
|
| 600 | + ev_bind_swizzle :: Bag EvBind -> Maybe (IdEnv Id)
|
|
| 601 | + -- Succeeds only if the bindings are all var-to-var bindings
|
|
| 602 | + ev_bind_swizzle evbs = foldl' do_one (Just emptyVarEnv) evbs
|
|
| 603 | + where
|
|
| 604 | + do_one :: Maybe (IdEnv Id) -> EvBind -> Maybe (IdEnv Id)
|
|
| 605 | + do_one Nothing _ = Nothing
|
|
| 606 | + do_one (Just swizzle) (EvBind {eb_lhs = bndr, eb_rhs = rhs})
|
|
| 607 | + = case rhs of
|
|
| 608 | + EvExpr (Var v) -> Just (extendVarEnv swizzle bndr v)
|
|
| 609 | + _ -> Nothing
|
|
| 610 | + |
|
| 361 | 611 | {-
|
| 362 | 612 | ************************************************************************
|
| 363 | 613 | * *
|
| ... | ... | @@ -1018,8 +1268,9 @@ pprHsWrapper wrap pp_thing_inside |
| 1018 | 1268 | -- True <=> appears in function application position
|
| 1019 | 1269 | -- False <=> appears as body of let or lambda
|
| 1020 | 1270 | help it WpHole = it
|
| 1021 | - help it (WpCompose f1 f2) = help (help it f2) f1
|
|
| 1022 | - help it (WpFun f1 f2 (Scaled w t1)) = add_parens $ text "\\(x" <> dcolon <> brackets (ppr w) <> ppr t1 <> text ")." <+>
|
|
| 1271 | + help it (WpCompose w1 w2) = help (help it w2) w1
|
|
| 1272 | + help it (WpSubType w) = no_parens $ text "subtype" <> braces (help it w False)
|
|
| 1273 | + help it (WpFun f1 f2 (Scaled w t1) _) = add_parens $ text "\\(x" <> dcolon <> brackets (ppr w) <> ppr t1 <> text ")." <+>
|
|
| 1023 | 1274 | help (\_ -> it True <+> help (\_ -> text "x") f1 True) f2 False
|
| 1024 | 1275 | help it (WpCast co) = add_parens $ sep [it False, nest 2 (text "|>"
|
| 1025 | 1276 | <+> pprParendCo co)]
|
| ... | ... | @@ -626,8 +626,12 @@ hasFixedRuntimeRep :: HasDebugCallStack |
| 626 | 626 | -- @ki@ is concrete, and @co :: ty ~# ty'@.
|
| 627 | 627 | -- That is, @ty'@ has a syntactically fixed RuntimeRep
|
| 628 | 628 | -- in the sense of Note [Fixed RuntimeRep].
|
| 629 | -hasFixedRuntimeRep frr_ctxt ty =
|
|
| 630 | - checkFRR_with (fmap (fmap coToMCo) . unifyConcrete_kind (fsLit "cx") . ConcreteFRR) frr_ctxt ty
|
|
| 629 | +hasFixedRuntimeRep frr_ctxt ty
|
|
| 630 | + = checkFRR_with unify_conc frr_ctxt ty
|
|
| 631 | + where
|
|
| 632 | + unify_conc frr_orig ki
|
|
| 633 | + = do { co <- unifyConcrete_kind (fsLit "cx") (ConcreteFRR frr_orig) ki
|
|
| 634 | + ; return (coToMCo co) }
|
|
| 631 | 635 | |
| 632 | 636 | -- | Like 'hasFixedRuntimeRep', but we perform an eager syntactic check.
|
| 633 | 637 | --
|
| ... | ... | @@ -148,7 +148,7 @@ matchActualFunTy |
| 148 | 148 | -- (Both are used only for error messages)
|
| 149 | 149 | -> TcRhoType
|
| 150 | 150 | -- ^ Type to analyse: a TcRhoType
|
| 151 | - -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)
|
|
| 151 | + -> TcM (TcCoercion, Scaled TcSigmaTypeFRR, TcSigmaType)
|
|
| 152 | 152 | -- This function takes in a type to analyse (a RhoType) and returns
|
| 153 | 153 | -- an argument type and a result type (splitting apart a function arrow).
|
| 154 | 154 | -- The returned argument type is a SigmaType with a fixed RuntimeRep;
|
| ... | ... | @@ -157,7 +157,7 @@ matchActualFunTy |
| 157 | 157 | -- See Note [matchActualFunTy error handling] for the first three arguments
|
| 158 | 158 | |
| 159 | 159 | -- If (wrap, arg_ty, res_ty) = matchActualFunTy ... fun_ty
|
| 160 | --- then wrap :: fun_ty ~> (arg_ty -> res_ty)
|
|
| 160 | +-- then wrap :: fun_ty ~~> (arg_ty -> res_ty)
|
|
| 161 | 161 | -- and NB: res_ty is an (uninstantiated) SigmaType
|
| 162 | 162 | |
| 163 | 163 | matchActualFunTy herald mb_thing err_info fun_ty
|
| ... | ... | @@ -172,13 +172,13 @@ matchActualFunTy herald mb_thing err_info fun_ty |
| 172 | 172 | -- hide the forall inside a meta-variable
|
| 173 | 173 | go :: TcRhoType -- The type we're processing, perhaps after
|
| 174 | 174 | -- expanding type synonyms
|
| 175 | - -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)
|
|
| 175 | + -> TcM (TcCoercion, Scaled TcSigmaTypeFRR, TcSigmaType)
|
|
| 176 | 176 | go ty | Just ty' <- coreView ty = go ty'
|
| 177 | 177 | |
| 178 | 178 | go (FunTy { ft_af = af, ft_mult = w, ft_arg = arg_ty, ft_res = res_ty })
|
| 179 | 179 | = assert (isVisibleFunArg af) $
|
| 180 | 180 | do { hasFixedRuntimeRep_syntactic (FRRExpectedFunTy herald 1) arg_ty
|
| 181 | - ; return (idHsWrapper, Scaled w arg_ty, res_ty) }
|
|
| 181 | + ; return (mkNomReflCo fun_ty, Scaled w arg_ty, res_ty) }
|
|
| 182 | 182 | |
| 183 | 183 | go ty@(TyVarTy tv)
|
| 184 | 184 | | isMetaTyVar tv
|
| ... | ... | @@ -210,7 +210,7 @@ matchActualFunTy herald mb_thing err_info fun_ty |
| 210 | 210 | ; res_ty <- newOpenFlexiTyVarTy
|
| 211 | 211 | ; let unif_fun_ty = mkScaledFunTys [arg_ty] res_ty
|
| 212 | 212 | ; co <- unifyType mb_thing fun_ty unif_fun_ty
|
| 213 | - ; return (mkWpCastN co, arg_ty, res_ty) }
|
|
| 213 | + ; return (co, arg_ty, res_ty) }
|
|
| 214 | 214 | |
| 215 | 215 | ------------
|
| 216 | 216 | mk_ctxt :: TcType -> TidyEnv -> ZonkM (TidyEnv, ErrCtxtMsg)
|
| ... | ... | @@ -249,8 +249,10 @@ matchActualFunTys :: ExpectedFunTyOrigin -- ^ See Note [Herald for matchExpected |
| 249 | 249 | -> Arity
|
| 250 | 250 | -> TcSigmaType
|
| 251 | 251 | -> TcM (HsWrapper, [Scaled TcSigmaTypeFRR], TcRhoType)
|
| 252 | --- If matchActualFunTys n ty = (wrap, [t1,..,tn], res_ty)
|
|
| 253 | --- then wrap : ty ~> (t1 -> ... -> tn -> res_ty)
|
|
| 252 | +-- NB: Called only from `tcSynArgA`, and hence scheduled for destruction
|
|
| 253 | +--
|
|
| 254 | +-- If matchActualFunTys n fun_ty = (wrap, [t1,..,tn], res_ty)
|
|
| 255 | +-- then wrap : fun_ty ~~> (t1 -> ... -> tn -> res_ty)
|
|
| 254 | 256 | -- and res_ty is a RhoType
|
| 255 | 257 | -- NB: the returned type is top-instantiated; it's a RhoType
|
| 256 | 258 | matchActualFunTys herald ct_orig n_val_args_wanted top_ty
|
| ... | ... | @@ -265,15 +267,13 @@ matchActualFunTys herald ct_orig n_val_args_wanted top_ty |
| 265 | 267 | go 0 _ fun_ty = return (idHsWrapper, [], fun_ty)
|
| 266 | 268 | |
| 267 | 269 | go n so_far fun_ty
|
| 268 | - = do { (wrap_fun1, arg_ty1, res_ty1) <- matchActualFunTy
|
|
| 269 | - herald Nothing
|
|
| 270 | - (n_val_args_wanted, top_ty)
|
|
| 271 | - fun_ty
|
|
| 272 | - ; (wrap_res, arg_tys, res_ty) <- go (n-1) (arg_ty1:so_far) res_ty1
|
|
| 270 | + = do { (co1, arg_ty1, res_ty1) <- matchActualFunTy herald Nothing
|
|
| 271 | + (n_val_args_wanted, top_ty) fun_ty
|
|
| 272 | + ; (wrap_res, arg_tys, res_ty) <- go (n-1) (arg_ty1:so_far) res_ty1
|
|
| 273 | 273 | ; let wrap_fun2 = mkWpFun idHsWrapper wrap_res arg_ty1 res_ty
|
| 274 | 274 | -- NB: arg_ty1 comes from matchActualFunTy, so it has
|
| 275 | - -- a syntactically fixed RuntimeRep as needed to call mkWpFun.
|
|
| 276 | - ; return (wrap_fun2 <.> wrap_fun1, arg_ty1:arg_tys, res_ty) }
|
|
| 275 | + -- a syntactically fixed RuntimeRep
|
|
| 276 | + ; return (wrap_fun2 <.> mkWpCastN co1, arg_ty1:arg_tys, res_ty) }
|
|
| 277 | 277 | |
| 278 | 278 | {-
|
| 279 | 279 | ************************************************************************
|
| ... | ... | @@ -459,7 +459,7 @@ tcSkolemiseGeneral ds_flag ctxt top_ty expected_ty thing_inside |
| 459 | 459 | tcSkolemiseCompleteSig :: TcCompleteSig
|
| 460 | 460 | -> ([ExpPatType] -> TcRhoType -> TcM result)
|
| 461 | 461 | -> TcM (HsWrapper, result)
|
| 462 | --- ^ The wrapper has type: spec_ty ~> expected_ty
|
|
| 462 | +-- ^ The wrapper has type: spec_ty ~~> expected_ty
|
|
| 463 | 463 | -- See Note [Skolemisation] for the differences between
|
| 464 | 464 | -- tcSkolemiseCompleteSig and tcTopSkolemise
|
| 465 | 465 | |
| ... | ... | @@ -790,7 +790,7 @@ matchExpectedFunTys :: forall a. |
| 790 | 790 | -> ([ExpPatType] -> ExpRhoType -> TcM a)
|
| 791 | 791 | -> TcM (HsWrapper, a)
|
| 792 | 792 | -- If matchExpectedFunTys n ty = (wrap, _)
|
| 793 | --- then wrap : (t1 -> ... -> tn -> ty_r) ~> ty,
|
|
| 793 | +-- then wrap : (t1 -> ... -> tn -> ty_r) ~~> ty,
|
|
| 794 | 794 | -- where [t1, ..., tn], ty_r are passed to the thing_inside
|
| 795 | 795 | --
|
| 796 | 796 | -- Unconditionally concludes by skolemising any trailing invisible
|
| ... | ... | @@ -865,12 +865,13 @@ matchExpectedFunTys herald ctx arity (Check top_ty) thing_inside |
| 865 | 865 | , ft_arg = arg_ty, ft_res = res_ty })
|
| 866 | 866 | = assert (isVisibleFunArg af) $
|
| 867 | 867 | do { let arg_pos = arity - n_req + 1 -- 1 for the first argument etc
|
| 868 | - ; (arg_co, arg_ty) <- hasFixedRuntimeRep (FRRExpectedFunTy herald arg_pos) arg_ty
|
|
| 868 | + ; (arg_co, arg_ty_frr) <- hasFixedRuntimeRep (FRRExpectedFunTy herald arg_pos) arg_ty
|
|
| 869 | + ; let arg_sty_frr = Scaled mult arg_ty_frr
|
|
| 869 | 870 | ; (wrap_res, result) <- check (n_req - 1)
|
| 870 | - (mkCheckExpFunPatTy (Scaled mult arg_ty) : rev_pat_tys)
|
|
| 871 | + (mkCheckExpFunPatTy arg_sty_frr : rev_pat_tys)
|
|
| 871 | 872 | res_ty
|
| 872 | 873 | ; let wrap_arg = mkWpCastN arg_co
|
| 873 | - fun_wrap = mkWpFun wrap_arg wrap_res (Scaled mult arg_ty) res_ty
|
|
| 874 | + fun_wrap = mkWpFun wrap_arg wrap_res arg_sty_frr res_ty
|
|
| 874 | 875 | ; return (fun_wrap, result) }
|
| 875 | 876 | |
| 876 | 877 | ----------------------------
|
| ... | ... | @@ -1407,7 +1408,7 @@ tcSubTypePat :: CtOrigin -> UserTypeCtxt |
| 1407 | 1408 | -- Used in patterns; polarity is backwards compared
|
| 1408 | 1409 | -- to tcSubType
|
| 1409 | 1410 | -- If wrap = tc_sub_type_et t1 t2
|
| 1410 | --- => wrap :: t1 ~> t2
|
|
| 1411 | +-- => wrap :: t1 ~~> t2
|
|
| 1411 | 1412 | tcSubTypePat inst_orig ctxt (Check ty_actual) ty_expected
|
| 1412 | 1413 | = tc_sub_type unifyTypeET inst_orig ctxt ty_actual ty_expected
|
| 1413 | 1414 | |
| ... | ... | @@ -1427,11 +1428,12 @@ tcSubTypeDS :: HsExpr GhcRn |
| 1427 | 1428 | -- DeepSubsumption <=> when checking, this type
|
| 1428 | 1429 | -- is deeply skolemised
|
| 1429 | 1430 | -> TcM HsWrapper
|
| 1430 | --- Only one call site, in GHC.Tc.Gen.App.tcApp
|
|
| 1431 | +-- Only one call site, in GHC.Tc.Gen.App.checkResultTy
|
|
| 1431 | 1432 | tcSubTypeDS rn_expr act_rho exp_rho
|
| 1432 | - = tc_sub_type_deep Top (unifyExprType rn_expr) orig GenSigCtxt act_rho exp_rho
|
|
| 1433 | - where
|
|
| 1434 | - orig = exprCtOrigin rn_expr
|
|
| 1433 | + = do { wrap <- tc_sub_type_deep Top (unifyExprType rn_expr)
|
|
| 1434 | + (exprCtOrigin rn_expr)
|
|
| 1435 | + GenSigCtxt act_rho exp_rho
|
|
| 1436 | + ; return (mkWpSubType wrap) }
|
|
| 1435 | 1437 | |
| 1436 | 1438 | ---------------
|
| 1437 | 1439 | |
| ... | ... | @@ -1456,7 +1458,7 @@ tcSubTypeSigma :: CtOrigin -- where did the actual type arise / why are we |
| 1456 | 1458 | -> TcSigmaType -> TcSigmaType -> TcM HsWrapper
|
| 1457 | 1459 | -- External entry point, but no ExpTypes on either side
|
| 1458 | 1460 | -- Checks that actual <= expected
|
| 1459 | --- Returns HsWrapper :: actual ~ expected
|
|
| 1461 | +-- Returns HsWrapper :: actual ~~> expected
|
|
| 1460 | 1462 | tcSubTypeSigma orig ctxt ty_actual ty_expected
|
| 1461 | 1463 | = tc_sub_type (unifyType Nothing) orig ctxt ty_actual ty_expected
|
| 1462 | 1464 | |
| ... | ... | @@ -1495,7 +1497,7 @@ tc_sub_type :: (TcType -> TcType -> TcM TcCoercionN) -- How to unify |
| 1495 | 1497 | -> TcM HsWrapper
|
| 1496 | 1498 | -- Checks that actual_ty is more polymorphic than expected_ty
|
| 1497 | 1499 | -- If wrap = tc_sub_type t1 t2
|
| 1498 | --- => wrap :: t1 ~> t2
|
|
| 1500 | +-- => wrap :: t1 ~~> t2
|
|
| 1499 | 1501 | --
|
| 1500 | 1502 | -- The "how to unify argument" is always a call to `uType TypeLevel orig`,
|
| 1501 | 1503 | -- but with different ways of constructing the CtOrigin `orig` from
|
| ... | ... | @@ -1504,7 +1506,8 @@ tc_sub_type :: (TcType -> TcType -> TcM TcCoercionN) -- How to unify |
| 1504 | 1506 | ----------------------
|
| 1505 | 1507 | tc_sub_type unify inst_orig ctxt ty_actual ty_expected
|
| 1506 | 1508 | = do { ds_flag <- getDeepSubsumptionFlag
|
| 1507 | - ; tc_sub_type_ds Top ds_flag unify inst_orig ctxt ty_actual ty_expected }
|
|
| 1509 | + ; wrap <- tc_sub_type_ds Top ds_flag unify inst_orig ctxt ty_actual ty_expected
|
|
| 1510 | + ; return (mkWpSubType wrap) }
|
|
| 1508 | 1511 | |
| 1509 | 1512 | ----------------------
|
| 1510 | 1513 | tc_sub_type_ds :: Position p -- ^ position in the type (for error messages only)
|
| ... | ... | @@ -1753,59 +1756,59 @@ we deal with function arrows. Suppose we have: |
| 1753 | 1756 | ty_actual = act_arg -> act_res
|
| 1754 | 1757 | ty_expected = exp_arg -> exp_res
|
| 1755 | 1758 | |
| 1756 | -To produce fun_wrap :: (act_arg -> act_res) ~> (exp_arg -> exp_res), we use
|
|
| 1759 | +To produce fun_wrap :: (act_arg -> act_res) ~~> (exp_arg -> exp_res), we use
|
|
| 1757 | 1760 | the fact that the function arrow is contravariant in its argument type and
|
| 1758 | 1761 | covariant in its result type. Thus we recursively perform subtype checks
|
| 1759 | 1762 | on the argument types (with actual/expected switched) and the result types,
|
| 1760 | 1763 | to get:
|
| 1761 | 1764 | |
| 1762 | - arg_wrap :: exp_arg ~> act_arg -- NB: expected/actual have switched sides
|
|
| 1763 | - res_wrap :: act_res ~> exp_res
|
|
| 1765 | + arg_wrap :: exp_arg ~~> act_arg -- NB: expected/actual have switched sides
|
|
| 1766 | + res_wrap :: act_res ~~> exp_res
|
|
| 1764 | 1767 | |
| 1765 | 1768 | Then fun_wrap = mkWpFun arg_wrap res_wrap.
|
| 1766 | 1769 | |
| 1767 | -Wrinkle [Representation-polymorphism checking during subtyping]
|
|
| 1770 | +Note [Representation-polymorphism checking during subtyping]
|
|
| 1771 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1772 | +When doing deep subsumption in `tc_sub_type_deep`, looking under function arrows,
|
|
| 1773 | +we would usually build a `WpFun` HsWrapper. When desugared, we get eta-expansion:
|
|
| 1768 | 1774 | |
| 1769 | - Inserting a WpFun HsWrapper amounts to impedance matching in deep subsumption
|
|
| 1770 | - via eta-expansion:
|
|
| 1775 | + f ==> \(x :: exp_arg). res_wrap [ f (arg_wrap [x]) ]
|
|
| 1771 | 1776 | |
| 1772 | - f ==> \ (x :: exp_arg) -> res_wrap [ f (arg_wrap [x]) ]
|
|
| 1777 | +Since we produce a lambda, we must enforce the representation polymorphism
|
|
| 1778 | +invariants described in Note [Representation polymorphism invariants] in GHC.Core.
|
|
| 1779 | +That is, we must ensure that both
|
|
| 1780 | + - x (the lambda binder), and
|
|
| 1781 | + - (arg_wrap [x]) (the function argument)
|
|
| 1782 | +have a fixed runtime representation.
|
|
| 1773 | 1783 | |
| 1774 | - As we produce a lambda, we must enforce the representation polymorphism
|
|
| 1775 | - invariants described in Note [Representation polymorphism invariants] in GHC.Core.
|
|
| 1776 | - That is, we must ensure that both x (the lambda binder) and (arg_wrap [x]) (the function argument)
|
|
| 1777 | - have a fixed runtime representation.
|
|
| 1784 | +But we don't /always/ need to produce a `WpFun`: if both argument and result wrappers
|
|
| 1785 | +are merely coercions, we can produce a `WpCast co` instead of a `WpFun`. In that
|
|
| 1786 | +case there is no eta-expansion, and hence no need for FRR checks.
|
|
| 1778 | 1787 | |
| 1779 | - Note however that desugaring mkWpFun does not always introduce a lambda: if
|
|
| 1780 | - both the argument and result HsWrappers are casts, then a FunCo cast suffices,
|
|
| 1781 | - in which case we should not perform representation-polymorphism checking.
|
|
| 1788 | +Here's a contrived example (there are undoubtedly more natural examples)
|
|
| 1789 | +(see testsuite/tests/rep-poly/NoEtaRequired):
|
|
| 1782 | 1790 | |
| 1783 | - This means that, in the FunTy/FunTy case of tc_sub_type_deep, we can skip
|
|
| 1784 | - the representation-polymorphism checks if the produced argument and result
|
|
| 1785 | - wrappers are identities or casts.
|
|
| 1786 | - It is important to do so, otherwise we reject valid programs.
|
|
| 1791 | + type Id :: k -> k
|
|
| 1792 | + type family Id a where
|
|
| 1787 | 1793 | |
| 1788 | - Here's a contrived example (there are undoubtedly more natural examples)
|
|
| 1789 | - (see testsuite/tests/rep-poly/NoEtaRequired):
|
|
| 1794 | + type T :: TYPE r -> TYPE (Id r)
|
|
| 1795 | + type family T a where
|
|
| 1790 | 1796 | |
| 1791 | - type Id :: k -> k
|
|
| 1792 | - type family Id a where
|
|
| 1797 | + test :: forall r (a :: TYPE r). a :~~: T a -> ()
|
|
| 1798 | + test HRefl =
|
|
| 1799 | + let
|
|
| 1800 | + f :: (a -> a) -> ()
|
|
| 1801 | + f _ = ()
|
|
| 1802 | + g :: T a -> T a
|
|
| 1803 | + g = undefined
|
|
| 1804 | + in f g
|
|
| 1793 | 1805 | |
| 1794 | - type T :: TYPE r -> TYPE (Id r)
|
|
| 1795 | - type family T a where
|
|
| 1806 | +We don't need to eta-expand `g` to make `f g` typecheck; a cast
|
|
| 1807 | +suffices. Hence we should not perform representation-polymorphism
|
|
| 1808 | +checks; they would fail here.
|
|
| 1796 | 1809 | |
| 1797 | - test :: forall r (a :: TYPE r). a :~~: T a -> ()
|
|
| 1798 | - test HRefl =
|
|
| 1799 | - let
|
|
| 1800 | - f :: (a -> a) -> ()
|
|
| 1801 | - f _ = ()
|
|
| 1802 | - g :: T a -> T a
|
|
| 1803 | - g = undefined
|
|
| 1804 | - in f g
|
|
| 1805 | - |
|
| 1806 | - We don't need to eta-expand `g` to make `f g` typecheck; a cast suffices.
|
|
| 1807 | - Hence we should not perform representation-polymorphism checks; they would
|
|
| 1808 | - fail here.
|
|
| 1810 | +All this is done by `mkWpFun_FRR`, which checks for the cast/cast case and
|
|
| 1811 | +returns a `FunCo` if so.
|
|
| 1809 | 1812 | |
| 1810 | 1813 | Note [Setting the argument context]
|
| 1811 | 1814 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1947,7 +1950,7 @@ getDeepSubsumptionFlag = do { ds <- xoptM LangExt.DeepSubsumption |
| 1947 | 1950 | -- | 'tc_sub_type_deep' is where the actual work happens for deep subsumption.
|
| 1948 | 1951 | --
|
| 1949 | 1952 | -- Given @ty_actual@ (a sigma-type) and @ty_expected@ (deeply skolemised, i.e.
|
| 1953 | +-- a deep rho type), it returns an 'HsWrapper' @wrap :: ty_actual ~~> ty_expected@.
|
|
| 1950 | 1954 | tc_sub_type_deep :: HasDebugCallStack
|
| 1951 | 1955 | => Position p -- ^ Position in the type (for error messages only)
|
| 1952 | 1956 | -> (TcType -> TcType -> TcM TcCoercionN) -- ^ How to unify
|
| ... | ... | @@ -1958,7 +1961,7 @@ tc_sub_type_deep :: HasDebugCallStack |
| 1958 | 1961 | -> TcM HsWrapper
|
| 1959 | 1962 | |
| 1960 | 1963 | -- If wrap = tc_sub_type_deep t1 t2
|
| 1961 | --- => wrap :: t1 ~> t2
|
|
| 1964 | +-- => wrap :: t1 ~~> t2
|
|
| 1962 | 1965 | -- Here is where the work actually happens!
|
| 1963 | 1966 | -- Precondition: ty_expected is deeply skolemised
|
| 1964 | 1967 | |
| ... | ... | @@ -2015,8 +2018,8 @@ tc_sub_type_deep pos unify inst_orig ctxt ty_actual ty_expected |
| 2015 | 2018 | ; unify_wrap <- just_unify exp_funTy ty_e
|
| 2016 | 2019 | ; fun_wrap <- go_fun af1 act_mult act_arg act_res af1 exp_mult exp_arg exp_res
|
| 2017 | 2020 | ; return $ unify_wrap <.> fun_wrap
|
| 2018 | - -- unify_wrap :: exp_funTy ~> ty_e
|
|
| 2019 | - -- fun_wrap :: ty_a ~> exp_funTy
|
|
| 2021 | + -- unify_wrap :: exp_funTy ~~> ty_e
|
|
| 2022 | + -- fun_wrap :: ty_a ~~> exp_funTy
|
|
| 2020 | 2023 | }
|
| 2021 | 2024 | go1 ty_a (FunTy { ft_af = af2, ft_mult = exp_mult, ft_arg = exp_arg, ft_res = exp_res })
|
| 2022 | 2025 | | isVisibleFunArg af2
|
| ... | ... | @@ -2028,8 +2031,8 @@ tc_sub_type_deep pos unify inst_orig ctxt ty_actual ty_expected |
| 2028 | 2031 | ; unify_wrap <- just_unify ty_a act_funTy
|
| 2029 | 2032 | ; fun_wrap <- go_fun af2 act_mult act_arg act_res af2 exp_mult exp_arg exp_res
|
| 2030 | 2033 | ; return $ fun_wrap <.> unify_wrap
|
| 2031 | - -- unify_wrap :: ty_a ~> act_funTy
|
|
| 2032 | - -- fun_wrap :: act_funTy ~> ty_e
|
|
| 2034 | + -- unify_wrap :: ty_a ~~> act_funTy
|
|
| 2035 | + -- fun_wrap :: act_funTy ~~> ty_e
|
|
| 2033 | 2036 | }
|
| 2034 | 2037 | |
| 2035 | 2038 | -- Otherwise, revert to unification.
|
| ... | ... | @@ -2064,17 +2067,28 @@ mkWpFun_FRR |
| 2064 | 2067 | -> Position p
|
| 2065 | 2068 | -> FunTyFlag -> Type -> TcType -> Type -- actual FunTy
|
| 2066 | 2069 | -> FunTyFlag -> Type -> TcType -> Type -- expected FunTy
|
| 2067 | - -> HsWrapper -- ^ exp_arg ~> act_arg
|
|
| 2068 | - -> HsWrapper -- ^ act_res ~> exp_res
|
|
| 2069 | - -> TcM HsWrapper -- ^ act_funTy ~> exp_funTy
|
|
| 2070 | + -> HsWrapper -- ^ exp_arg ~~> act_arg
|
|
| 2071 | + -> HsWrapper -- ^ act_res ~~> exp_res
|
|
| 2072 | + -> TcM HsWrapper -- ^ (act_arg->act_res) ~~> (exp_arg->exp_res)
|
|
| 2070 | 2073 | mkWpFun_FRR unify pos act_af act_mult act_arg act_res exp_af exp_mult exp_arg exp_res arg_wrap res_wrap
|
| 2071 | - = do { ((exp_arg_co, exp_arg_frr), (act_arg_co, _act_arg_frr)) <-
|
|
| 2072 | - if needs_frr_checks
|
|
| 2073 | - -- See Wrinkle [Representation-polymorphism checking during subtyping]
|
|
| 2074 | - then do { exp_frr_wrap <- hasFixedRuntimeRep (frr_ctxt True ) exp_arg
|
|
| 2075 | - ; act_frr_wrap <- hasFixedRuntimeRep (frr_ctxt False) act_arg
|
|
| 2076 | - ; return (exp_frr_wrap, act_frr_wrap) }
|
|
| 2077 | - else return ((mkNomReflCo exp_arg, exp_arg), (mkNomReflCo act_arg, act_arg))
|
|
| 2074 | + | Just arg_co <- getWpCo_maybe arg_wrap act_arg -- arg_co :: exp_arg ~R# act_arg
|
|
| 2075 | + , Just res_co <- getWpCo_maybe res_wrap act_res -- res_co :: act_res ~R# exp_res
|
|
| 2076 | + = -- The argument and result wrappers are both hole or cast;
|
|
| 2077 | + -- so we can make do with a FunCo
|
|
| 2078 | + -- See Note [Representation-polymorphism checking during subtyping]
|
|
| 2079 | + do { mult_co <- unify act_mult exp_mult
|
|
| 2080 | + ; let the_co = mkFunCo2 Representational act_af exp_af mult_co (mkSymCo arg_co) res_co
|
|
| 2081 | + ; return (mkWpCastR the_co) }
|
|
| 2082 | + |
|
| 2083 | + | otherwise
|
|
| 2084 | + = -- We need a full WpFun, with the eta-expansion that it entails
|
|
| 2085 | + -- And hence we must add fixed-runtime-rep checks so that the eta-expansion is OK
|
|
| 2086 | + -- See Note [Representation-polymorphism checking during subtyping]
|
|
| 2087 | + do { (exp_arg_co, exp_arg_frr) <- hasFixedRuntimeRep (frr_ctxt True ) exp_arg
|
|
| 2088 | + ; (act_arg_co, _act_arg_frr) <- hasFixedRuntimeRep (frr_ctxt False) act_arg
|
|
| 2089 | + -- exp_arg_frr, act_arg_frr :: Type have fixed runtime-reps
|
|
| 2090 | + -- exp_arg_co :: exp_arg ~ exp_arg_frr Usually Refl
|
|
| 2091 | + -- act_arg_co :: act_arg ~ act_arg_frr Usually Refl
|
|
| 2078 | 2092 | |
| 2079 | 2093 | -- Enforce equality of multiplicities (not the more natural sub-multiplicity).
|
| 2080 | 2094 | -- See Note [Multiplicity in deep subsumption]
|
| ... | ... | @@ -2083,46 +2097,36 @@ mkWpFun_FRR unify pos act_af act_mult act_arg act_res exp_af exp_mult exp_arg ex |
| 2083 | 2097 | -- equality to be Refl, but it might well not be (#26332).
|
| 2084 | 2098 | |
| 2085 | 2099 | ; let
|
| 2086 | - exp_arg_fun_co =
|
|
| 2100 | + exp_arg_fun_co = -- (exp_arg_frr -> exp_res) ~ (exp_arg -> exp_res)
|
|
| 2087 | 2101 | mkFunCo Nominal exp_af
|
| 2088 | - (mkReflCo Nominal exp_mult)
|
|
| 2102 | + (mkNomReflCo exp_mult)
|
|
| 2089 | 2103 | (mkSymCo exp_arg_co)
|
| 2090 | - (mkReflCo Nominal exp_res)
|
|
| 2091 | - act_arg_fun_co =
|
|
| 2104 | + (mkNomReflCo exp_res)
|
|
| 2105 | + act_arg_fun_co = -- (act_arg -> act_res) ~ (act_arg_frr -> act_res)
|
|
| 2092 | 2106 | mkFunCo Nominal act_af
|
| 2093 | 2107 | act_arg_mult_co
|
| 2094 | 2108 | act_arg_co
|
| 2095 | - (mkReflCo Nominal act_res)
|
|
| 2096 | - arg_wrap_frr =
|
|
| 2109 | + (mkNomReflCo act_res)
|
|
| 2110 | + arg_wrap_frr = -- exp_arg_frr ~~> act_arg_frr
|
|
| 2097 | 2111 | mkWpCastN (mkSymCo exp_arg_co) <.> arg_wrap <.> mkWpCastN act_arg_co
|
| 2098 | - -- exp_arg_co :: exp_arg ~> exp_arg_frr
|
|
| 2099 | - -- act_arg_co :: act_arg ~> act_arg_frr
|
|
| 2100 | - -- arg_wrap :: exp_arg ~> act_arg
|
|
| 2101 | - -- arg_wrap_frr :: exp_arg_frr ~> act_arg_frr
|
|
| 2102 | 2112 | |
| 2103 | - ; return $
|
|
| 2104 | - mkWpCastN exp_arg_fun_co
|
|
| 2113 | + ; return $ -- Whole thing :: (act_arg->act_res) ~~> (exp_arg->exp_ress)
|
|
| 2114 | + mkWpCastN exp_arg_fun_co -- (exp_ar_frr->exp_res) ~~> (exp_arg->exp_res)
|
|
| 2105 | 2115 | <.>
|
| 2106 | 2116 | mkWpFun arg_wrap_frr res_wrap (Scaled exp_mult exp_arg_frr) exp_res
|
| 2107 | - <.>
|
|
| 2108 | - mkWpCastN act_arg_fun_co
|
|
| 2117 | + <.> -- (act_arg_frr->act_res) ~~> (exp_arg_frr->exp_res)
|
|
| 2118 | + mkWpCastN act_arg_fun_co -- (act_arg->act_res) ~~> (act_arg_frr->act_res)
|
|
| 2109 | 2119 | }
|
| 2110 | 2120 | where
|
| 2111 | - needs_frr_checks :: Bool
|
|
| 2112 | - needs_frr_checks =
|
|
| 2113 | - not (hole_or_cast arg_wrap)
|
|
| 2114 | - ||
|
|
| 2115 | - not (hole_or_cast res_wrap)
|
|
| 2116 | - hole_or_cast :: HsWrapper -> Bool
|
|
| 2117 | - hole_or_cast WpHole = True
|
|
| 2118 | - hole_or_cast (WpCast {}) = True
|
|
| 2119 | - hole_or_cast _ = False
|
|
| 2121 | + getWpCo_maybe :: HsWrapper -> Type -> Maybe CoercionR
|
|
| 2122 | + -- See if a HsWrapper is just a coercion
|
|
| 2123 | + getWpCo_maybe WpHole ty = Just (mkRepReflCo ty)
|
|
| 2124 | + getWpCo_maybe (WpCast co) _ = Just co
|
|
| 2125 | + getWpCo_maybe _ _ = Nothing
|
|
| 2126 | + |
|
| 2120 | 2127 | frr_ctxt :: Bool -> FixedRuntimeRepContext
|
| 2121 | - frr_ctxt is_exp_ty =
|
|
| 2122 | - FRRDeepSubsumption
|
|
| 2123 | - { frrDSExpected = is_exp_ty
|
|
| 2124 | - , frrDSPosition = pos
|
|
| 2125 | - }
|
|
| 2128 | + frr_ctxt is_exp_ty = FRRDeepSubsumption { frrDSExpected = is_exp_ty
|
|
| 2129 | + , frrDSPosition = pos }
|
|
| 2126 | 2130 | |
| 2127 | 2131 | -----------------------
|
| 2128 | 2132 | deeplySkolemise :: SkolemInfo -> TcSigmaType
|
| ... | ... | @@ -2146,9 +2150,9 @@ deeplySkolemise skol_info ty |
| 2146 | 2150 | ; let tvs = binderVars bndrs
|
| 2147 | 2151 | tvs1 = binderVars bndrs1
|
| 2148 | 2152 | tv_prs1 = map tyVarName tvs `zip` bndrs1
|
| 2149 | - ; return ( mkWpEta ids1 (mkWpTyLams tvs1
|
|
| 2150 | - <.> mkWpEvLams ev_vars1
|
|
| 2151 | - <.> wrap)
|
|
| 2153 | + ; return ( mkWpEta ty ids1 (mkWpTyLams tvs1
|
|
| 2154 | + <.> mkWpEvLams ev_vars1
|
|
| 2155 | + <.> wrap)
|
|
| 2152 | 2156 | , tv_prs1 ++ tvs_prs2
|
| 2153 | 2157 | , ev_vars1 ++ ev_vars2
|
| 2154 | 2158 | , mkScaledFunTys arg_tys' rho ) }
|
| ... | ... | @@ -2182,7 +2186,7 @@ deeplyInstantiate orig ty |
| 2182 | 2186 | ; ids1 <- newSysLocalIds (fsLit "di") arg_tys'
|
| 2183 | 2187 | ; wrap1 <- instCall orig (mkTyVarTys tvs') theta'
|
| 2184 | 2188 | ; (wrap2, rho2) <- go subst' rho
|
| 2185 | - ; return (mkWpEta ids1 (wrap2 <.> wrap1),
|
|
| 2189 | + ; return (mkWpEta ty ids1 (wrap2 <.> wrap1),
|
|
| 2186 | 2190 | mkScaledFunTys arg_tys' rho2) }
|
| 2187 | 2191 | |
| 2188 | 2192 | | otherwise
|
| ... | ... | @@ -1233,13 +1233,16 @@ zonk_cmd_top (HsCmdTop (CmdTopTc stack_tys ty ids) cmd) |
| 1233 | 1233 | -------------------------------------------------------------------------
|
| 1234 | 1234 | zonkCoFn :: HsWrapper -> ZonkBndrTcM HsWrapper
|
| 1235 | 1235 | zonkCoFn WpHole = return WpHole
|
| 1236 | +zonkCoFn (WpSubType w) = do { w' <- zonkCoFn w
|
|
| 1237 | + ; return (WpSubType w') }
|
|
| 1236 | 1238 | zonkCoFn (WpCompose c1 c2) = do { c1' <- zonkCoFn c1
|
| 1237 | 1239 | ; c2' <- zonkCoFn c2
|
| 1238 | 1240 | ; return (WpCompose c1' c2') }
|
| 1239 | -zonkCoFn (WpFun c1 c2 t1) = do { c1' <- zonkCoFn c1
|
|
| 1240 | - ; c2' <- zonkCoFn c2
|
|
| 1241 | - ; t1' <- noBinders $ zonkScaledTcTypeToTypeX t1
|
|
| 1242 | - ; return (WpFun c1' c2' t1') }
|
|
| 1241 | +zonkCoFn (WpFun c1 c2 t1 t2) = do { c1' <- zonkCoFn c1
|
|
| 1242 | + ; c2' <- zonkCoFn c2
|
|
| 1243 | + ; t1' <- noBinders $ zonkScaledTcTypeToTypeX t1
|
|
| 1244 | + ; t2' <- noBinders $ zonkTcTypeToTypeX t2
|
|
| 1245 | + ; return (WpFun c1' c2' t1' t2') }
|
|
| 1243 | 1246 | zonkCoFn (WpCast co) = WpCast <$> noBinders (zonkCoToCo co)
|
| 1244 | 1247 | zonkCoFn (WpEvLam ev) = WpEvLam <$> zonkEvBndrX ev
|
| 1245 | 1248 | zonkCoFn (WpEvApp arg) = WpEvApp <$> noBinders (zonkEvTerm arg)
|
| 1 | +{-# LANGUAGE DeepSubsumption, RankNTypes #-}
|
|
| 2 | +module T26349 where
|
|
| 3 | + |
|
| 4 | +{-# SPECIALIZE INLINE mapTCMT :: (forall b. IO b -> IO b) -> IO a -> IO a #-}
|
|
| 5 | +mapTCMT :: (forall b. m b -> n b) -> m a -> n a
|
|
| 6 | +mapTCMT f m = f m
|
|
| 7 | + |
|
| 8 | +{-
|
|
| 9 | + We'll check
|
|
| 10 | + tcExpr (mapTCMT) (Check ((forall b. IO b -> IO b) -> IO a_sk -> IO a_sk))
|
|
| 11 | +-} |
| 1 | +==================== Tidy Core rules ====================
|
|
| 2 | +"USPEC mapTCMT @(*) @IO @IO @_"
|
|
| 3 | + forall (@a). mapTCMT @(*) @IO @IO @a = mapTCMT_$smapTCMT @a |
| ... | ... | @@ -559,3 +559,4 @@ test('T26051', [ grep_errmsg(r'\$wspecMe') |
| 559 | 559 | test('T26115', [grep_errmsg(r'DFun')], compile, ['-O -ddump-simpl -dsuppress-uniques'])
|
| 560 | 560 | test('T26116', normal, compile, ['-O -ddump-rules'])
|
| 561 | 561 | test('T26117', [grep_errmsg(r'==')], compile, ['-O -ddump-simpl -dsuppress-uniques'])
|
| 562 | +test('T26349', normal, compile, ['-O -ddump-rules']) |
| ... | ... | @@ -10,18 +10,15 @@ |
| 10 | 10 | |
| 11 | 11 | |
| 12 | 12 | ==================== Grand total simplifier statistics ====================
|
| 13 | -Total ticks: 13
|
|
| 13 | +Total ticks: 11
|
|
| 14 | 14 | |
| 15 | -2 PreInlineUnconditionally
|
|
| 16 | - 1 ds
|
|
| 17 | - 1 f
|
|
| 15 | +1 PreInlineUnconditionally 1 f
|
|
| 18 | 16 | 2 UnfoldingDone
|
| 19 | 17 | 1 GHC.Internal.Base.id
|
| 20 | 18 | 1 Roman.bar
|
| 21 | 19 | 1 RuleFired 1 foo/bar
|
| 22 | 20 | 1 LetFloatFromLet 1
|
| 23 | -7 BetaReduction
|
|
| 24 | - 1 ds
|
|
| 21 | +6 BetaReduction
|
|
| 25 | 22 | 1 f
|
| 26 | 23 | 1 a
|
| 27 | 24 | 1 m
|