Adam Gundry pushed to branch wip/amg/castz at Glasgow Haskell Compiler / GHC

Commits:

12 changed files:

Changes:

  • compiler/GHC/Core/Coercion.hs
    ... ... @@ -56,6 +56,14 @@ module GHC.Core.Coercion (
    56 56
             -- ** Cast coercions
    
    57 57
             castCoToCo,
    
    58 58
             mkTransCastCo, mkTransCastCoCo, mkTransCoCastCo,
    
    59
    +        mkSymCastCo,
    
    60
    +        mkPiCastCos,
    
    61
    +        isReflCastCo,
    
    62
    +        checkReflexiveCastCo,
    
    63
    +        coToCastCo,
    
    64
    +        mkForAllCastCo,
    
    65
    +        mkFunResCastCo,
    
    66
    +        mkFunCastCoNoFTF,
    
    59 67
     
    
    60 68
             -- ** Decomposition
    
    61 69
             instNewTyCon_maybe,
    
    ... ... @@ -82,7 +90,7 @@ module GHC.Core.Coercion (
    82 90
     
    
    83 91
             coToMCo, kindCoToMKindCo,
    
    84 92
             mkTransMCo, mkTransMCoL, mkTransMCoR, mkCastTyMCo, mkSymMCo,
    
    85
    -        mkFunResMCo, mkPiMCos,
    
    93
    +        mkFunResMCo,
    
    86 94
             isReflMCo, checkReflexiveMCo,
    
    87 95
     
    
    88 96
             -- ** Coercion variables
    
    ... ... @@ -389,13 +397,10 @@ mkCastTyMCo :: Type -> MCoercion -> Type
    389 397
     mkCastTyMCo ty MRefl    = ty
    
    390 398
     mkCastTyMCo ty (MCo co) = ty `mkCastTy` co
    
    391 399
     
    
    392
    -mkPiMCos :: [Var] -> MCoercion -> MCoercion
    
    393
    -mkPiMCos _ MRefl = MRefl
    
    394
    -mkPiMCos vs (MCo co) = MCo (mkPiCos Representational vs co)
    
    395
    -
    
    396
    -mkFunResMCo :: Id -> MCoercionR -> MCoercionR
    
    397
    -mkFunResMCo _      MRefl    = MRefl
    
    398
    -mkFunResMCo arg_id (MCo co) = MCo (mkFunResCo Representational arg_id co)
    
    400
    +mkFunResMCo :: Id -> CastCoercion -> CastCoercion
    
    401
    +mkFunResMCo _      ReflCastCo    = ReflCastCo
    
    402
    +mkFunResMCo arg_id (CCoercion co) = CCoercion (mkFunResCo Representational arg_id co)
    
    403
    +mkFunResMCo arg_id (ZCoercion ty cos) = ZCoercion (mkFunctionType (idMult arg_id) (varType arg_id) ty) cos -- TODO check type
    
    399 404
     
    
    400 405
     mkGReflLeftMCo :: Role -> Type -> MCoercionN -> Coercion
    
    401 406
     mkGReflLeftMCo r ty MRefl    = mkReflCo r ty
    
    ... ... @@ -842,6 +847,17 @@ mkFunCoNoFTF r w arg_co res_co
    842 847
         Pair argl_ty argr_ty = coercionKind arg_co
    
    843 848
         Pair resl_ty resr_ty = coercionKind res_co
    
    844 849
     
    
    850
    +-- AMG TODO: more cases here, or maybe better to have a FunCo constructor of CastCoercion?
    
    851
    +mkFunCastCoNoFTF :: HasDebugCallStack => Role -> Mult -> Type -> CastCoercion -> Type -> CastCoercion -> CastCoercion
    
    852
    +mkFunCastCoNoFTF _ mult _ (ZCoercion arg_ty arg_cos) _ (ZCoercion res_ty res_cos) = ZCoercion (mkFunctionType mult arg_ty res_ty) (arg_cos `unionVarSet` res_cos)
    
    853
    +mkFunCastCoNoFTF _ mult _ (ZCoercion arg_ty arg_cos) res_ty res_co = ZCoercion (mkFunctionType mult arg_ty (castCoercionRKind res_ty res_co)) (arg_cos `unionVarSet` coVarsOfCastCo res_co)
    
    854
    +mkFunCastCoNoFTF _ mult arg_ty arg_co _ (ZCoercion res_ty res_cos) = ZCoercion (mkFunctionType mult (castCoercionRKind arg_ty arg_co) res_ty) (res_cos `unionVarSet` coVarsOfCastCo arg_co)
    
    855
    +mkFunCastCoNoFTF r mult _ (CCoercion arg_co) _ (CCoercion res_co) = CCoercion (mkFunCoNoFTF r (multToCo mult) arg_co res_co)
    
    856
    +mkFunCastCoNoFTF _ _ _ ReflCastCo _ ReflCastCo = ReflCastCo
    
    857
    +mkFunCastCoNoFTF r mult _ (CCoercion arg_co) res_ty ReflCastCo = CCoercion (mkFunCoNoFTF r (multToCo mult) arg_co (mkReflCo r res_ty))
    
    858
    +mkFunCastCoNoFTF r mult arg_ty ReflCastCo _ (CCoercion res_co) = CCoercion (mkFunCoNoFTF r (multToCo mult) (mkReflCo r arg_ty) res_co)
    
    859
    +
    
    860
    +
    
    845 861
     -- | Build a function 'Coercion' from two other 'Coercion's. That is,
    
    846 862
     -- given @co1 :: a ~ b@ and @co2 :: x ~ y@ produce @co :: (a -> x) ~ (b -> y)@
    
    847 863
     -- or @(a => x) ~ (b => y)@, depending on the kind of @a@/@b@.
    
    ... ... @@ -968,6 +984,13 @@ mkForAllCo v visL visR kind_co co
    968 984
       | otherwise
    
    969 985
       = mk_forall_co v visL visR kind_co co
    
    970 986
     
    
    987
    +mkForAllCastCo :: HasDebugCallStack => TyCoVar -> ForAllTyFlag -> ForAllTyFlag
    
    988
    +            -> CastCoercion -> CastCoercion
    
    989
    +mkForAllCastCo v visL visR cco = case cco of
    
    990
    +    CCoercion co -> CCoercion (mkForAllCo v visL visR MRefl co)
    
    991
    +    ZCoercion ty cos -> ZCoercion (mkTyCoForAllTy v visL ty) cos
    
    992
    +    ReflCastCo -> ReflCastCo
    
    993
    +
    
    971 994
     -- mkForAllVisCos [tv{vis}] constructs a cast
    
    972 995
     --   forall tv. res  ~R#   forall tv{vis} res`.
    
    973 996
     -- See Note [Required foralls in Core] in GHC.Core.TyCo.Rep
    
    ... ... @@ -1187,6 +1210,14 @@ mkSymCo co@(ForAllCo { fco_kind = kco, fco_body = body_co })
    1187 1210
       | isReflMCo kco          = co { fco_body = mkSymCo body_co }
    
    1188 1211
     mkSymCo co                 = SymCo co
    
    1189 1212
     
    
    1213
    +-- | Variant of 'mkSymCo' that works on 'CastCoercion', and expects the LHS type
    
    1214
    +-- of the input coercion (and hence the RHS type of the result coercion) to be
    
    1215
    +-- passed in.
    
    1216
    +mkSymCastCo :: Type -> CastCoercion -> CastCoercion
    
    1217
    +mkSymCastCo _  (CCoercion co)    = CCoercion (mkSymCo co)
    
    1218
    +mkSymCastCo ty (ZCoercion _ cos) = ZCoercion ty cos
    
    1219
    +mkSymCastCo _  ReflCastCo        = ReflCastCo
    
    1220
    +
    
    1190 1221
     -- | mkTransCo creates a new 'Coercion' by composing the two
    
    1191 1222
     --   given 'Coercion's transitively: (co1 ; co2)
    
    1192 1223
     mkTransCo :: HasDebugCallStack => Coercion -> Coercion -> Coercion
    
    ... ... @@ -1765,6 +1796,9 @@ castCoercionKind g h1 h2
    1765 1796
     mkPiCos :: Role -> [Var] -> Coercion -> Coercion
    
    1766 1797
     mkPiCos r vs co = foldr (mkPiCo r) co vs
    
    1767 1798
     
    
    1799
    +mkPiCastCos :: Role -> [Var] -> CastCoercion -> CastCoercion
    
    1800
    +mkPiCastCos r vs co = foldr (mkPiCastCo r) co vs
    
    1801
    +
    
    1768 1802
     -- | Make a forall 'Coercion', where both types related by the coercion
    
    1769 1803
     -- are quantified over the same variable.
    
    1770 1804
     mkPiCo  :: Role -> Var -> Coercion -> Coercion
    
    ... ... @@ -1778,6 +1812,16 @@ mkPiCo r v co | isTyVar v = mkHomoForAllCo v co
    1778 1812
                                 mkFunResCo r v co
    
    1779 1813
                   | otherwise = mkFunResCo r v co
    
    1780 1814
     
    
    1815
    +mkPiCastCo  :: Role -> Var -> CastCoercion -> CastCoercion
    
    1816
    +mkPiCastCo _ _ ReflCastCo     = ReflCastCo
    
    1817
    +mkPiCastCo r v (CCoercion co) = CCoercion (mkPiCo r v co)
    
    1818
    +mkPiCastCo r v (ZCoercion ty cos)
    
    1819
    +  | isTyVar v = ZCoercion (mkForAllTy (Bndr v vis) ty) cos
    
    1820
    +  | otherwise = ZCoercion (mkFunctionType (idMult v) (varType v) ty) cos
    
    1821
    +  where
    
    1822
    +    vis = coreTyLamForAllTyFlag
    
    1823
    +
    
    1824
    +
    
    1781 1825
     mkFunResCo :: Role -> Id -> Coercion -> Coercion
    
    1782 1826
     -- Given res_co :: res1 ~ res2,
    
    1783 1827
     --   mkFunResCo r m arg res_co :: (arg -> res1) ~r (arg -> res2)
    
    ... ... @@ -1788,6 +1832,13 @@ mkFunResCo role id res_co
    1788 1832
         arg_co = mkReflCo role (varType id)
    
    1789 1833
         mult   = multToCo (idMult id)
    
    1790 1834
     
    
    1835
    +mkFunResCastCo :: Role -> Id -> CastCoercion -> CastCoercion
    
    1836
    +mkFunResCastCo role id res_cco = case res_cco of
    
    1837
    +    CCoercion res_co -> CCoercion (mkFunResCo role id res_co)
    
    1838
    +    ZCoercion ty cos -> ZCoercion (mkFunctionType (idMult id) (varType id) ty) cos
    
    1839
    +    ReflCastCo -> ReflCastCo
    
    1840
    +
    
    1841
    +
    
    1791 1842
     -- mkCoCast (c :: s1 ~?r t1) (g :: (s1 ~?r t1) ~#R (s2 ~?r t2)) :: s2 ~?r t2
    
    1792 1843
     -- The first coercion might be lifted or unlifted; thus the ~? above
    
    1793 1844
     -- Lifted and unlifted equalities take different numbers of arguments,
    
    ... ... @@ -2873,7 +2924,7 @@ See Note [Zapped casts] in GHC.Core.TyCo.Rep.
    2873 2924
     -- but requires the type to be supplied by the caller because it cannot be
    
    2874 2925
     -- recovered in the 'ZCoercion' case.
    
    2875 2926
     castCoercionLKind :: HasDebugCallStack => Type -> CastCoercion -> Type
    
    2876
    -castCoercionLKind _ (CCoercion co) = coercionLKind co
    
    2927
    +castCoercionLKind _ (CCoercion co) = coercionLKind co -- TODO: should we use provided lhs_ty instead? Not sure which is cheaper?
    
    2877 2928
     castCoercionLKind lhs_ty (ZCoercion _ _) = lhs_ty
    
    2878 2929
     castCoercionLKind lhs_ty ReflCastCo = lhs_ty
    
    2879 2930
     
    
    ... ... @@ -2922,9 +2973,27 @@ mkTransCoCastCo co1 (CCoercion co2) = CCoercion (mkTransCo co1 co2)
    2922 2973
     mkTransCoCastCo co1 (ZCoercion ty cos) = ZCoercion ty (shallowCoVarsOfCo co1 `unionVarSet` cos)
    
    2923 2974
     mkTransCoCastCo co1 ReflCastCo         = CCoercion co1
    
    2924 2975
     
    
    2976
    +-- | Quickly check if a 'CastCoercion' is obviously reflexive.
    
    2977
    +isReflCastCo :: CastCoercion -> Bool
    
    2978
    +isReflCastCo (CCoercion co) = isReflCo co
    
    2979
    +isReflCastCo ZCoercion{}    = False  -- it might be, but we can't tell
    
    2980
    +isReflCastCo ReflCastCo     = True
    
    2981
    +
    
    2925 2982
     -- | Slowly checks if the coercion is reflexive. Don't call this in a loop,
    
    2926 2983
     -- as it walks over the entire coercion.
    
    2927 2984
     isReflexiveCastCo :: Type -> CastCoercion -> Bool
    
    2928 2985
     isReflexiveCastCo _      (CCoercion co) = isReflexiveCo co
    
    2929 2986
     isReflexiveCastCo lhs_ty (ZCoercion rhs_ty _) = lhs_ty `eqType` rhs_ty
    
    2930 2987
     isReflexiveCastCo _      ReflCastCo           = True
    
    2988
    +
    
    2989
    +checkReflexiveCastCo :: Type -> CastCoercion -> CastCoercion
    
    2990
    +checkReflexiveCastCo ty cco
    
    2991
    +  | isReflexiveCastCo ty cco = ReflCastCo
    
    2992
    +  | otherwise                = cco
    
    2993
    +
    
    2994
    +coToCastCo :: Coercion -> CastCoercion
    
    2995
    +-- Convert a coercion to a CastCoercion, checking if it is obviously reflexive.
    
    2996
    +-- It's not clear whether or not isReflexiveCo would be better here
    
    2997
    +--    See #19815 for a bit of data and discussion on this point
    
    2998
    +coToCastCo co | isReflCo co = ReflCastCo
    
    2999
    +              | otherwise   = CCoercion co

  • compiler/GHC/Core/Coercion/Opt.hs
    ... ... @@ -4,6 +4,7 @@
    4 4
     
    
    5 5
     module GHC.Core.Coercion.Opt
    
    6 6
        ( optCoercion
    
    7
    +   , optCastCoercion
    
    7 8
        , OptCoercionOpts (..)
    
    8 9
        )
    
    9 10
     where
    
    ... ... @@ -169,6 +170,13 @@ newtype OptCoercionOpts = OptCoercionOpts
    169 170
        { optCoercionEnabled :: Bool  -- ^ Enable coercion optimisation (reduce its size)
    
    170 171
        }
    
    171 172
     
    
    173
    +optCastCoercion :: OptCoercionOpts -> Subst -> Type -> CastCoercion -> CastCoercion
    
    174
    +optCastCoercion opts env _ (CCoercion co) = CCoercion (optCoercion opts env co)
    
    175
    +optCastCoercion opts env _ ReflCastCo     = ReflCastCo
    
    176
    +optCastCoercion opts env tyL (ZCoercion tyR cos)
    
    177
    +  | tyL `eqTypeIgnoringMultiplicity` tyR = ReflCastCo
    
    178
    +  | otherwise        = ZCoercion (substTy env tyR) (substCoVarSet env cos)
    
    179
    +
    
    172 180
     optCoercion :: OptCoercionOpts -> Subst -> Coercion -> NormalCo
    
    173 181
     -- ^ optCoercion applies a substitution to a coercion,
    
    174 182
     --   *and* optimises it to reduce its size
    

  • compiler/GHC/Core/Map/Type.hs
    ... ... @@ -139,6 +139,7 @@ xtC (D env co) f (CoercionMapX m)
    139 139
     
    
    140 140
     -- We should really never care about the contents of a cast coercion. Instead,
    
    141 141
     -- just look up the coercion's RHS type.
    
    142
    +-- TODO: do we need this type, or can we just use TypeMap?
    
    142 143
     newtype CastCoercionMap a = CastCoercionMap (CastCoercionMapG a)
    
    143 144
     
    
    144 145
     -- TODO(22292): derive
    

  • compiler/GHC/Core/Opt/Arity.hs
    ... ... @@ -42,7 +42,7 @@ module GHC.Core.Opt.Arity
    42 42
        , etaExpandToJoinPoint, etaExpandToJoinPointRule
    
    43 43
     
    
    44 44
        -- ** Coercions and casts
    
    45
    -   , pushCoArg, pushCoArgs, pushCoValArg, pushCoTyArg
    
    45
    +   , pushCoArg, pushCoArgs, pushCastCoValArg, pushCastCoTyArg
    
    46 46
        , pushCoercionIntoLambda, pushCoDataCon, collectBindersPushingCo
    
    47 47
        )
    
    48 48
     where
    
    ... ... @@ -2195,7 +2195,7 @@ Now, when we push that eta_co inward in etaInfoApp:
    2195 2195
     -}
    
    2196 2196
     
    
    2197 2197
     --------------
    
    2198
    -data EtaInfo = EI [Var] MCoercionR
    
    2198
    +data EtaInfo = EI [Var] CastCoercion
    
    2199 2199
          -- See Note [The EtaInfo mechanism]
    
    2200 2200
     
    
    2201 2201
     instance Outputable EtaInfo where
    
    ... ... @@ -2221,11 +2221,10 @@ etaInfoApp in_scope expr eis
    2221 2221
         go subst (Tick t e) eis
    
    2222 2222
           = Tick (substTickish subst t) (go subst e eis)
    
    2223 2223
     
    
    2224
    -    go subst (Cast e cco) (EI bs mco)
    
    2224
    +    go subst (Cast e co) (EI bs mco)
    
    2225 2225
           = go subst e (EI bs mco')
    
    2226 2226
           where
    
    2227
    -        co = castCoToCo (exprType e) cco -- TODO: can we avoid this?
    
    2228
    -        mco' = checkReflexiveMCo (Core.substCo subst co `mkTransMCoR` mco)
    
    2227
    +        mco' = checkReflexiveCastCo (exprType (Core.substExpr subst e)) (Core.substCastCo subst co `mkTransCastCo` mco)
    
    2229 2228
                    -- See Note [Check for reflexive casts in eta expansion]
    
    2230 2229
     
    
    2231 2230
         go subst (Case e b ty alts) eis
    
    ... ... @@ -2247,13 +2246,13 @@ etaInfoApp in_scope expr eis
    2247 2246
         -- Beta-reduction if possible, pushing any intervening casts past
    
    2248 2247
         -- the argument. See Note [The EtaInfo mechanism]
    
    2249 2248
         go subst (Lam v e) (EI (b:bs) mco)
    
    2250
    -      | Just (arg,mco') <- pushMCoArg mco (varToCoreExpr b)
    
    2249
    +      | Just (arg,mco') <- pushCoArg (exprType (Lam v e)) mco (varToCoreExpr b)
    
    2251 2250
           = go (Core.extendSubst subst v arg) e (EI bs mco')
    
    2252 2251
     
    
    2253 2252
         -- Stop pushing down; just wrap the expression up
    
    2254 2253
         -- See Note [Check for reflexive casts in eta expansion]
    
    2255 2254
         go subst e (EI bs mco) = Core.substExprSC subst e
    
    2256
    -                             `mkCastMCo` checkReflexiveMCo mco
    
    2255
    +                             `mkCastCo` checkReflexiveCastCo (exprType e) mco -- TODO check type
    
    2257 2256
                                  `mkVarApps` bs
    
    2258 2257
     
    
    2259 2258
     --------------
    
    ... ... @@ -2263,14 +2262,12 @@ etaInfoAppTy :: Type -> EtaInfo -> Type
    2263 2262
     etaInfoAppTy ty (EI bs mco)
    
    2264 2263
       = applyTypeToArgs ty1 (map varToCoreExpr bs)
    
    2265 2264
       where
    
    2266
    -    ty1 = case mco of
    
    2267
    -             MRefl  -> ty
    
    2268
    -             MCo co -> coercionRKind co
    
    2265
    +    ty1 = castCoercionRKind ty mco
    
    2269 2266
     
    
    2270 2267
     --------------
    
    2271 2268
     etaInfoAbs :: EtaInfo -> CoreExpr -> CoreExpr
    
    2272 2269
     -- See Note [The EtaInfo mechanism]
    
    2273
    -etaInfoAbs (EI bs mco) expr = (mkLams bs expr) `mkCastMCo` mkSymMCo mco
    
    2270
    +etaInfoAbs (EI bs mco) expr = (mkLams bs expr) `mkCastCo` mkSymCastCo (error "AMG TODO: etaInfoAbs") mco
    
    2274 2271
     
    
    2275 2272
     --------------
    
    2276 2273
     -- | @mkEtaWW n _ fvs ty@ will compute the 'EtaInfo' necessary for eta-expanding
    
    ... ... @@ -2307,7 +2304,7 @@ mkEtaWW orig_oss ppr_orig_expr in_scope orig_ty
    2307 2304
     
    
    2308 2305
         go _ [] subst _
    
    2309 2306
            ----------- Done!  No more expansion needed
    
    2310
    -       = (substInScopeSet subst, EI [] MRefl)
    
    2307
    +       = (substInScopeSet subst, EI [] ReflCastCo)
    
    2311 2308
     
    
    2312 2309
         go n oss@(one_shot:oss1) subst ty
    
    2313 2310
            ----------- Forall types  (forall a. ty)
    
    ... ... @@ -2348,27 +2345,28 @@ mkEtaWW orig_oss ppr_orig_expr in_scope orig_ty
    2348 2345
                  --  we'd have had to zap it for the recursive call)
    
    2349 2346
            , (in_scope, EI bs mco) <- go n oss subst ty'
    
    2350 2347
              -- mco :: subst(ty') ~ b1_ty -> ... -> bn_ty -> tr
    
    2351
    -       = (in_scope, EI bs (mkTransMCoR co' mco))
    
    2348
    +       = (in_scope, EI bs (mkTransCoCastCo co' mco))
    
    2352 2349
     
    
    2353 2350
            | otherwise       -- We have an expression of arity > 0,
    
    2354 2351
                              -- but its type isn't a function, or a binder
    
    2355 2352
                              -- does not have a fixed runtime representation
    
    2356 2353
            = warnPprTrace True "mkEtaWW" ((ppr orig_oss <+> ppr orig_ty) $$ ppr_orig_expr)
    
    2357
    -         (substInScopeSet subst, EI [] MRefl)
    
    2354
    +         (substInScopeSet subst, EI [] ReflCastCo)
    
    2358 2355
             -- This *can* legitimately happen:
    
    2359 2356
             -- e.g.  coerce Int (\x. x) Essentially the programmer is
    
    2360 2357
             -- playing fast and loose with types (Happy does this a lot).
    
    2361 2358
             -- So we simply decline to eta-expand.  Otherwise we'd end up
    
    2362 2359
             -- with an explicit lambda having a non-function type
    
    2363 2360
     
    
    2364
    -mkEtaForAllMCo :: ForAllTyBinder -> Type -> MCoercion -> MCoercion
    
    2361
    +mkEtaForAllMCo :: ForAllTyBinder -> Type -> CastCoercion -> CastCoercion
    
    2365 2362
     mkEtaForAllMCo (Bndr tcv vis) ty mco
    
    2366 2363
       = case mco of
    
    2367
    -      MRefl | vis == coreTyLamForAllTyFlag -> MRefl
    
    2368
    -            | otherwise                    -> mk_fco (mkRepReflCo ty)
    
    2369
    -      MCo co                               -> mk_fco co
    
    2364
    +      ReflCastCo | vis == coreTyLamForAllTyFlag -> ReflCastCo
    
    2365
    +                 | otherwise                    -> mk_fco (mkRepReflCo ty)
    
    2366
    +      CCoercion co                              -> mk_fco co
    
    2367
    +      ZCoercion ty2 cos                         -> ZCoercion ty cos -- TODO: is ty right? 
    
    2370 2368
       where
    
    2371
    -    mk_fco co = MCo (mkForAllCo tcv vis coreTyLamForAllTyFlag MRefl co)
    
    2369
    +    mk_fco co = CCoercion (mkForAllCo tcv vis coreTyLamForAllTyFlag MRefl co)
    
    2372 2370
         -- coreTyLamForAllTyFlag: See Note [The EtaInfo mechanism], particularly
    
    2373 2371
         -- the (EtaInfo Invariant).  (sym co) wraps a lambda that always has
    
    2374 2372
         -- a ForAllTyFlag of coreTyLamForAllTyFlag; see Note [Required foralls in Core]
    
    ... ... @@ -2701,13 +2699,13 @@ same fix.
    2701 2699
     tryEtaReduce :: UnVarSet -> [Var] -> CoreExpr -> SubDemand -> Maybe CoreExpr
    
    2702 2700
     -- Return an expression equal to (\bndrs. body)
    
    2703 2701
     tryEtaReduce rec_ids bndrs body eval_sd
    
    2704
    -  = go (reverse bndrs) body (mkRepReflCo (exprType body))
    
    2702
    +  = go (reverse bndrs) body ReflCastCo
    
    2705 2703
       where
    
    2706 2704
         incoming_arity = count isId bndrs -- See Note [Eta reduction makes sense], point (2)
    
    2707 2705
     
    
    2708 2706
         go :: [Var]            -- Binders, innermost first, types [a3,a2,a1]
    
    2709 2707
            -> CoreExpr         -- Of type tr
    
    2710
    -       -> Coercion         -- Of type tr ~ ts
    
    2708
    +       -> CastCoercion     -- Of type tr ~ ts
    
    2711 2709
            -> Maybe CoreExpr   -- Of type a1 -> a2 -> a3 -> ts
    
    2712 2710
         -- See Note [Eta reduction with casted arguments]
    
    2713 2711
         -- for why we have an accumulating coercion
    
    ... ... @@ -2717,7 +2715,7 @@ tryEtaReduce rec_ids bndrs body eval_sd
    2717 2715
     
    
    2718 2716
         -- See Note [Eta reduction with casted function]
    
    2719 2717
         go bs (Cast e co1) co2
    
    2720
    -      = go bs e (castCoToCo (exprType e) co1 `mkTransCo` co2)
    
    2718
    +      = go bs e (co1 `mkTransCastCo` co2)
    
    2721 2719
     
    
    2722 2720
         go bs (Tick t e) co
    
    2723 2721
           | tickishFloatable t
    
    ... ... @@ -2740,7 +2738,7 @@ tryEtaReduce rec_ids bndrs body eval_sd
    2740 2738
           , remaining_bndrs `ltLength` bndrs
    
    2741 2739
                 -- Only reply Just if /something/ has happened
    
    2742 2740
           , ok_fun fun
    
    2743
    -      , let used_vars     = exprFreeVars fun `unionVarSet` tyCoVarsOfCo co
    
    2741
    +      , let used_vars     = exprFreeVars fun `unionVarSet` tyCoVarsOfCastCo co
    
    2744 2742
                 reduced_bndrs = mkVarSet (dropList remaining_bndrs bndrs)
    
    2745 2743
                 -- reduced_bndrs are the ones we are eta-reducing away
    
    2746 2744
           , used_vars `disjointVarSet` reduced_bndrs
    
    ... ... @@ -2749,7 +2747,7 @@ tryEtaReduce rec_ids bndrs body eval_sd
    2749 2747
               -- See Note [Eta reduction makes sense], intro and point (1)
    
    2750 2748
               -- NB: don't compute used_vars from exprFreeVars (mkCast fun co)
    
    2751 2749
               --     because the latter may be ill formed if the guard fails (#21801)
    
    2752
    -      = Just (mkLams (reverse remaining_bndrs) (mkCast fun co))
    
    2750
    +      = Just (mkLams (reverse remaining_bndrs) (mkCastCo fun co))
    
    2753 2751
     
    
    2754 2752
         go _remaining_bndrs _fun  _  = -- pprTrace "tER fail" (ppr _fun $$ ppr _remaining_bndrs) $
    
    2755 2753
                                        Nothing
    
    ... ... @@ -2797,10 +2795,10 @@ tryEtaReduce rec_ids bndrs body eval_sd
    2797 2795
         ---------------
    
    2798 2796
         ok_arg :: Var              -- Of type bndr_t
    
    2799 2797
                -> CoreExpr         -- Of type arg_t
    
    2800
    -           -> Coercion         -- Of kind (t1~t2)
    
    2798
    +           -> CastCoercion     -- Of kind (t1~t2)
    
    2801 2799
                -> Type             -- Type (arg_t -> t1) of the function
    
    2802 2800
                                    --      to which the argument is supplied
    
    2803
    -           -> Maybe (Coercion  -- Of type (arg_t -> t1 ~  bndr_t -> t2)
    
    2801
    +           -> Maybe (CastCoercion  -- Of type (arg_t -> t1 ~  bndr_t -> t2)
    
    2804 2802
                                    --   (and similarly for tyvars, coercion args)
    
    2805 2803
                         , [CoreTickish])
    
    2806 2804
         -- See Note [Eta reduction with casted arguments]
    
    ... ... @@ -2808,7 +2806,7 @@ tryEtaReduce rec_ids bndrs body eval_sd
    2808 2806
            | Just tv <- getTyVar_maybe arg_ty
    
    2809 2807
            , bndr == tv  = case splitForAllForAllTyBinder_maybe fun_ty of
    
    2810 2808
                Just (Bndr _ vis, _) -> Just (fco, [])
    
    2811
    -             where !fco = mkForAllCo tv vis coreTyLamForAllTyFlag MRefl co
    
    2809
    +             where !fco = mkForAllCastCo tv vis coreTyLamForAllTyFlag co
    
    2812 2810
                        -- The lambda we are eta-reducing always has visibility
    
    2813 2811
                        -- 'coreTyLamForAllTyFlag' which may or may not match
    
    2814 2812
                        -- the visibility on the inner function (#24014)
    
    ... ... @@ -2821,13 +2819,13 @@ tryEtaReduce rec_ids bndrs body eval_sd
    2821 2819
            , let mult = idMult bndr
    
    2822 2820
            , Just (_af, fun_mult, _, _) <- splitFunTy_maybe fun_ty
    
    2823 2821
            , mult `eqType` fun_mult -- There is no change in multiplicity, otherwise we must abort
    
    2824
    -       = Just (mkFunResCo Representational bndr co, [])
    
    2822
    +       = Just (mkFunResCastCo Representational bndr co, [])
    
    2825 2823
         ok_arg bndr (Cast e co_arg) co fun_ty
    
    2826 2824
            | (ticks, Var v) <- stripTicksTop tickishFloatable e
    
    2827
    -       , Just (_, fun_mult, _, _) <- splitFunTy_maybe fun_ty
    
    2825
    +       , Just (_, fun_mult, _, res_ty) <- splitFunTy_maybe fun_ty
    
    2828 2826
            , bndr == v
    
    2829 2827
            , fun_mult `eqType` idMult bndr
    
    2830
    -       = Just (mkFunCoNoFTF Representational (multToCo fun_mult) (mkSymCo (castCoToCo (exprType e) co_arg)) co, ticks)
    
    2828
    +       = Just (mkFunCastCoNoFTF Representational fun_mult (castCoercionRKind (exprType e) co_arg) (mkSymCastCo (exprType e) co_arg) res_ty co, ticks) -- TODO check types
    
    2831 2829
            -- The simplifier combines multiple casts into one,
    
    2832 2830
            -- so we can have a simple-minded pattern match here
    
    2833 2831
         ok_arg bndr (Tick t arg) co fun_ty
    
    ... ... @@ -2873,43 +2871,44 @@ Here we implement the "push rules" from FC papers:
    2873 2871
       by pushing the coercion into the arguments
    
    2874 2872
     -}
    
    2875 2873
     
    
    2876
    -pushCoArgs :: CoercionR -> [CoreArg] -> Maybe ([CoreArg], MCoercion)
    
    2877
    -pushCoArgs co []         = return ([], MCo co)
    
    2878
    -pushCoArgs co (arg:args) = do { (arg',  m_co1) <- pushCoArg  co  arg
    
    2879
    -                              ; case m_co1 of
    
    2880
    -                                  MCo co1 -> do { (args', m_co2) <- pushCoArgs co1 args
    
    2881
    -                                                 ; return (arg':args', m_co2) }
    
    2882
    -                                  MRefl  -> return (arg':args, MRefl) }
    
    2883
    -
    
    2884
    -pushMCoArg :: MCoercionR -> CoreArg -> Maybe (CoreArg, MCoercion)
    
    2885
    -pushMCoArg MRefl    arg = Just (arg, MRefl)
    
    2886
    -pushMCoArg (MCo co) arg = pushCoArg co arg
    
    2887
    -
    
    2888
    -pushCoArg :: CoercionR -> CoreArg -> Maybe (CoreArg, MCoercion)
    
    2874
    +pushCoArgs :: Type -> CastCoercion -> [CoreArg] -> Maybe ([CoreArg], CastCoercion)
    
    2875
    +pushCoArgs _ co []         = return ([], co)
    
    2876
    +pushCoArgs fun_ty co (arg:args) = do
    
    2877
    +    { (arg',  m_co1) <- pushCoArg fun_ty co arg
    
    2878
    +    ; if isReflCastCo m_co1
    
    2879
    +        then return (arg':args, ReflCastCo)
    
    2880
    +        else do { (args', m_co2) <- pushCoArgs (funResultTy fun_ty) m_co1 args -- TODO check type
    
    2881
    +                ; return (arg':args', m_co2) }
    
    2882
    +    }
    
    2883
    +
    
    2884
    +pushCoArg :: Type -> CastCoercion -> CoreArg -> Maybe (CoreArg, CastCoercion)
    
    2889 2885
     -- We have (fun |> co) arg, and we want to transform it to
    
    2890 2886
     --         (fun arg) |> co
    
    2891 2887
     -- This may fail, e.g. if (fun :: N) where N is a newtype
    
    2892 2888
     -- C.f. simplCast in GHC.Core.Opt.Simplify
    
    2893 2889
     -- 'co' is always Representational
    
    2894
    -pushCoArg co arg
    
    2890
    +pushCoArg fun_ty co arg
    
    2895 2891
       | Type ty <- arg
    
    2896
    -  = do { (ty', m_co') <- pushCoTyArg co ty
    
    2892
    +  = do { (ty', m_co') <- pushCastCoTyArg co ty
    
    2897 2893
            ; return (Type ty', m_co') }
    
    2898 2894
       | otherwise
    
    2899
    -  = do { (arg_mco, m_co') <- pushCoValArg co
    
    2900
    -       ; let arg_mco' = checkReflexiveMCo arg_mco
    
    2901
    -             -- checkReflexiveMCo: see Note [Check for reflexive casts in eta expansion]
    
    2895
    +  = do { (arg_mco, m_co') <- pushCastCoValArg fun_ty co
    
    2896
    +       ; let arg_mco' = checkReflexiveCastCo (funArgTy fun_ty) arg_mco
    
    2897
    +             -- checkReflexiveCastCo: see Note [Check for reflexive casts in eta expansion]
    
    2902 2898
                  -- The coercion is very often (arg_co -> res_co), but without
    
    2903 2899
                  -- the argument coercion actually being ReflCo
    
    2904
    -       ; return (arg `mkCastMCo` arg_mco', m_co') }
    
    2900
    +       ; return (arg `mkCastCo` arg_mco', m_co') }
    
    2901
    +
    
    2902
    +pushCastCoTyArg :: CastCoercion -> Type -> Maybe (Type, CastCoercion)
    
    2903
    +pushCastCoTyArg (CCoercion co)         ty = pushCoTyArg co ty
    
    2904
    +pushCastCoTyArg ReflCastCo             ty = Just (ty, ReflCastCo)
    
    2905
    +pushCastCoTyArg (ZCoercion fun_ty cos) ty = Nothing -- TODO do better
    
    2905 2906
     
    
    2906
    -pushCoTyArg :: CoercionR -> Type -> Maybe (Type, MCoercionR)
    
    2907
    +pushCoTyArg :: CoercionR -> Type -> Maybe (Type, CastCoercion)
    
    2907 2908
     -- We have (fun |> co) @ty
    
    2908 2909
     -- Push the coercion through to return
    
    2909 2910
     --         (fun @ty') |> co'
    
    2910 2911
     -- 'co' is always Representational
    
    2911
    --- If the returned coercion is Nothing, then it would have been reflexive;
    
    2912
    --- it's faster not to compute it, though.
    
    2913 2912
     pushCoTyArg co ty
    
    2914 2913
       -- The following is inefficient - don't do `eqType` here, the coercion
    
    2915 2914
       -- optimizer will take care of it. See #14737.
    
    ... ... @@ -2917,11 +2916,11 @@ pushCoTyArg co ty
    2917 2916
       -- -- = Just (ty, Nothing)
    
    2918 2917
     
    
    2919 2918
       | isReflCo co
    
    2920
    -  = Just (ty, MRefl)
    
    2919
    +  = Just (ty, ReflCastCo)
    
    2921 2920
     
    
    2922 2921
       | isForAllTy_ty tyL
    
    2923 2922
       = assertPpr (isForAllTy_ty tyR) (ppr co $$ ppr ty) $
    
    2924
    -    Just (ty `mkCastTy` co1, MCo co2)
    
    2923
    +    Just (ty `mkCastTy` co1, CCoercion co2)
    
    2925 2924
     
    
    2926 2925
       | otherwise
    
    2927 2926
       = Nothing
    
    ... ... @@ -2941,6 +2940,18 @@ pushCoTyArg co ty
    2941 2940
             -- co2 :: ty1[ (ty|>co1)/a1 ] ~R ty2[ ty/a2 ]
    
    2942 2941
             -- Arg of mkInstCo is always nominal, hence Nominal
    
    2943 2942
     
    
    2943
    +pushCastCoValArg :: Type -> CastCoercion -> Maybe (CastCoercion, CastCoercion)
    
    2944
    +pushCastCoValArg _ ReflCastCo         = Just (ReflCastCo, ReflCastCo)
    
    2945
    +pushCastCoValArg _ (CCoercion co)     = pushCoValArg co
    
    2946
    +pushCastCoValArg tyL (ZCoercion tyR cos)
    
    2947
    +  | isFunTy tyL  -- TODO: do we need to check this or can we assume it?
    
    2948
    +  , isFunTy tyR
    
    2949
    +  , typeHasFixedRuntimeRep new_arg_ty
    
    2950
    +              = Just (ZCoercion new_arg_ty cos, ZCoercion (funResultTy tyR) cos)
    
    2951
    +  | otherwise = Nothing
    
    2952
    +  where
    
    2953
    +    new_arg_ty = funArgTy tyR
    
    2954
    +
    
    2944 2955
     -- | If @pushCoValArg co = Just (co_arg, co_res)@, then
    
    2945 2956
     --
    
    2946 2957
     -- > (\x.body) |> co  =  (\y. let { x = y |> co_arg } in body) |> co_res)
    
    ... ... @@ -2952,7 +2963,7 @@ pushCoTyArg co ty
    2952 2963
     -- If the LHS is well-typed, then so is the RHS. In particular, the argument
    
    2953 2964
     -- @arg |> co_arg@ is guaranteed to have a fixed 'RuntimeRep', in the sense of
    
    2954 2965
     -- Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.
    
    2955
    -pushCoValArg :: CoercionR -> Maybe (MCoercionR, MCoercionR)
    
    2966
    +pushCoValArg :: CoercionR -> Maybe (CastCoercion, CastCoercion)
    
    2956 2967
     pushCoValArg co
    
    2957 2968
       -- The following is inefficient - don't do `eqType` here, the coercion
    
    2958 2969
       -- optimizer will take care of it. See #14737.
    
    ... ... @@ -2960,7 +2971,7 @@ pushCoValArg co
    2960 2971
       -- -- = Just (mkRepReflCo arg, Nothing)
    
    2961 2972
     
    
    2962 2973
       | isReflCo co
    
    2963
    -  = Just (MRefl, MRefl)
    
    2974
    +  = Just (ReflCastCo, ReflCastCo)
    
    2964 2975
     
    
    2965 2976
       | isFunTy tyL
    
    2966 2977
       , (_, co1, co2) <- decomposeFunCo co
    
    ... ... @@ -2979,8 +2990,8 @@ pushCoValArg co
    2979 2990
          (vcat [ text "co:" <+> ppr co
    
    2980 2991
                , text "old_arg_ty:" <+> ppr old_arg_ty
    
    2981 2992
                , text "new_arg_ty:" <+> ppr new_arg_ty ]) $
    
    2982
    -    Just (coToMCo (mkSymCo co1), coToMCo co2)
    
    2983
    -    -- Critically, coToMCo to checks for ReflCo; the whole coercion may not
    
    2993
    +    Just (coToCastCo (mkSymCo co1), coToCastCo co2)
    
    2994
    +    -- Critically, coToCastCo to checks for ReflCo; the whole coercion may not
    
    2984 2995
         -- be reflexive, but either of its components might be
    
    2985 2996
         -- We could use isReflexiveCo, but it's not clear if the benefit
    
    2986 2997
         -- is worth the cost, and it makes no difference in #18223
    
    ... ... @@ -2993,13 +3004,14 @@ pushCoValArg co
    2993 3004
         Pair tyL tyR = coercionKind co
    
    2994 3005
     
    
    2995 3006
     pushCoercionIntoLambda
    
    2996
    -    :: HasDebugCallStack => Subst -> InVar -> InExpr -> OutCoercionR -> Maybe (OutVar, OutExpr)
    
    3007
    +    :: HasDebugCallStack => Subst -> InVar -> InExpr -> OutCastCoercion -> Maybe (OutVar, OutExpr)
    
    2997 3008
     -- This implements the Push rule from the paper on coercions
    
    2998 3009
     --    (\x. e) |> co
    
    2999 3010
     -- ===>
    
    3000 3011
     --    (\x'. e |> co')
    
    3001
    -pushCoercionIntoLambda subst x e co
    
    3012
    +pushCoercionIntoLambda subst x e cco
    
    3002 3013
         | assert (not (isTyVar x) && not (isCoVar x)) True
    
    3014
    +    , CCoercion co <- cco -- AMG TODO: support for other CastCoercions
    
    3003 3015
         , Pair s1s2 t1t2 <- coercionKind co
    
    3004 3016
         , Just {}              <- splitFunTy_maybe s1s2
    
    3005 3017
         , Just (_, w1, t1,_t2) <- splitFunTy_maybe t1t2
    
    ... ... @@ -3024,7 +3036,7 @@ pushCoercionIntoLambda subst x e co
    3024 3036
         | otherwise
    
    3025 3037
         = Nothing
    
    3026 3038
     
    
    3027
    -pushCoDataCon :: DataCon -> [CoreExpr] -> MCoercionR
    
    3039
    +pushCoDataCon :: DataCon -> [CoreExpr] -> CastCoercion
    
    3028 3040
                   -> Maybe (DataCon
    
    3029 3041
                            , [Type]      -- Universal type args
    
    3030 3042
                            , [CoreExpr]) -- All other args incl existentials
    
    ... ... @@ -3034,8 +3046,9 @@ pushCoDataCon :: DataCon -> [CoreExpr] -> MCoercionR
    3034 3046
     -- where co :: (T t1 .. tn) ~ (T s1 .. sn)
    
    3035 3047
     -- The left-hand one must be a T, because exprIsConApp returned True
    
    3036 3048
     -- but the right-hand one might not be.  (Though it usually will.)
    
    3037
    -pushCoDataCon dc dc_args MRefl    = Just $! (push_dc_refl dc dc_args)
    
    3038
    -pushCoDataCon dc dc_args (MCo co) = push_dc_gen  dc dc_args co (coercionKind co)
    
    3049
    +pushCoDataCon dc dc_args ReflCastCo = Just $! (push_dc_refl dc dc_args)
    
    3050
    +pushCoDataCon dc dc_args (CCoercion co) = push_dc_gen  dc dc_args co (coercionKind co)
    
    3051
    +pushCoDataCon dc dc_args (ZCoercion ty cos) = Nothing -- AMG TODO: pushCoDataCon
    
    3039 3052
     
    
    3040 3053
     push_dc_refl :: DataCon -> [CoreExpr] -> (DataCon, [Type], [CoreExpr])
    
    3041 3054
     push_dc_refl dc dc_args
    

  • compiler/GHC/Core/Opt/OccurAnal.hs
    ... ... @@ -36,7 +36,7 @@ import GHC.Prelude hiding ( head, init, last, tail )
    36 36
     import GHC.Core
    
    37 37
     import GHC.Core.FVs
    
    38 38
     import GHC.Core.Utils   ( exprIsTrivial, isDefaultAlt, isExpandableApp,
    
    39
    -                          mkCastMCo, mkTicks )
    
    39
    +                          mkCastCo, mkTicks )
    
    40 40
     import GHC.Core.Opt.Arity   ( joinRhsArity, isOneShotBndr )
    
    41 41
     import GHC.Core.Coercion
    
    42 42
     import GHC.Core.Type
    
    ... ... @@ -2853,7 +2853,7 @@ data OccEnv
    2853 2853
                -- If  x :-> (y, co)  is in the env,
    
    2854 2854
                -- then please replace x by (y |> mco)
    
    2855 2855
                -- Invariant of course: idType x = exprType (y |> mco)
    
    2856
    -           , occ_bs_env  :: !(IdEnv (OutId, MCoercion))
    
    2856
    +           , occ_bs_env  :: !(IdEnv (OutId, CastCoercion))
    
    2857 2857
                   -- Domain is Global and Local Ids
    
    2858 2858
                   -- Range is just Local Ids
    
    2859 2859
                , occ_bs_rng  :: !VarSet
    
    ... ... @@ -3455,7 +3455,7 @@ addBndrSwap scrut case_bndr
    3455 3455
           -- Do not add [x :-> x] to occ_bs_env, else lookupBndrSwap will loop
    
    3456 3456
       = env { occ_bs_env = extendVarEnv swap_env scrut_var (case_bndr', mco)
    
    3457 3457
             , occ_bs_rng = rng_vars `extendVarSet` case_bndr'
    
    3458
    -                       `unionVarSet` tyCoVarsOfMCo mco }
    
    3458
    +                       `unionVarSet` tyCoVarsOfCastCo mco }
    
    3459 3459
     
    
    3460 3460
       | otherwise
    
    3461 3461
       = env
    
    ... ... @@ -3466,7 +3466,7 @@ addBndrSwap scrut case_bndr
    3466 3466
     -- | See bBinderSwaOk.
    
    3467 3467
     data BinderSwapDecision
    
    3468 3468
       = NoBinderSwap
    
    3469
    -  | DoBinderSwap OutVar MCoercion
    
    3469
    +  | DoBinderSwap OutVar CastCoercion
    
    3470 3470
     
    
    3471 3471
     scrutOkForBinderSwap :: OutExpr -> BinderSwapDecision
    
    3472 3472
     -- If (scrutOkForBinderSwap e = DoBinderSwap v mco, then
    
    ... ... @@ -3479,8 +3479,8 @@ scrutOkForBinderSwap :: OutExpr -> BinderSwapDecision
    3479 3479
     scrutOkForBinderSwap e
    
    3480 3480
       = case e of
    
    3481 3481
           Tick _ e        -> scrutOkForBinderSwap e  -- Drop ticks
    
    3482
    -      Var v           -> DoBinderSwap v MRefl
    
    3483
    -      Cast (Var v) co -> DoBinderSwap v (MCo (mkSymCo (castCoToCo (idType v) co))) -- TODO: can we do better?
    
    3482
    +      Var v           -> DoBinderSwap v ReflCastCo
    
    3483
    +      Cast (Var v) co -> DoBinderSwap v (mkSymCastCo (idType v) co)
    
    3484 3484
                              -- Cast: see Note [Case of cast]
    
    3485 3485
           _               -> NoBinderSwap
    
    3486 3486
     
    
    ... ... @@ -3495,7 +3495,7 @@ lookupBndrSwap env@(OccEnv { occ_bs_env = bs_env }) bndr
    3495 3495
         -- Why do we iterate here?
    
    3496 3496
         -- See (BS2) in Note [The binder-swap substitution]
    
    3497 3497
         case lookupBndrSwap env bndr1 of
    
    3498
    -      (fun, fun_id) -> (mkCastMCo fun mco, fun_id) }
    
    3498
    +      (fun, fun_id) -> (mkCastCo fun mco, fun_id) }
    
    3499 3499
     
    
    3500 3500
     {- Historical note [Proxy let-bindings]
    
    3501 3501
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -19,6 +19,7 @@ import GHC.Core.Opt.Simplify.Monad
    19 19
     import GHC.Core.Opt.ConstantFold
    
    20 20
     import GHC.Core.Type hiding ( substCo, substTy, substTyVar, extendTvSubst, extendCvSubst )
    
    21 21
     import GHC.Core.TyCo.Compare( eqType )
    
    22
    +import GHC.Core.TyCo.Subst ( substCoVarSet )
    
    22 23
     import GHC.Core.Opt.Simplify.Env
    
    23 24
     import GHC.Core.Opt.Simplify.Inline
    
    24 25
     import GHC.Core.Opt.Simplify.Utils
    
    ... ... @@ -36,7 +37,7 @@ import GHC.Core.Unfold
    36 37
     import GHC.Core.Unfold.Make
    
    37 38
     import GHC.Core.Utils
    
    38 39
     import GHC.Core.Opt.Arity ( ArityType, exprArity, arityTypeBotSigs_maybe
    
    39
    -                          , pushCoTyArg, pushCoValArg, exprIsDeadEnd
    
    40
    +                          , pushCastCoTyArg, pushCastCoValArg, exprIsDeadEnd
    
    40 41
                               , typeArity, arityTypeArity, etaExpandAT )
    
    41 42
     import GHC.Core.SimpleOpt ( exprIsConApp_maybe, joinPointBinding_maybe, joinPointBindings_maybe )
    
    42 43
     import GHC.Core.FVs     ( mkRuleInfo {- exprsFreeIds -} )
    
    ... ... @@ -54,6 +55,7 @@ import GHC.Types.Unique ( hasKey )
    54 55
     import GHC.Types.Basic
    
    55 56
     import GHC.Types.Tickish
    
    56 57
     import GHC.Types.Var    ( isTyCoVar )
    
    58
    +import GHC.Types.Var.Set
    
    57 59
     import GHC.Builtin.Types.Prim( realWorldStatePrimTy )
    
    58 60
     import GHC.Builtin.Names( runRWKey, seqHashKey )
    
    59 61
     
    
    ... ... @@ -644,7 +646,7 @@ tryCastWorkerWrapper env bind_cxt old_bndr bndr (Cast rhs co)
    644 646
         mk_worker_unfolding top_lvl work_id work_rhs
    
    645 647
           = case realUnfoldingInfo info of -- NB: the real one, even for loop-breakers
    
    646 648
                unf@(CoreUnfolding { uf_tmpl = unf_rhs, uf_src = src })
    
    647
    -             | isStableSource src -> return (unf { uf_tmpl = mkCast unf_rhs (mkSymCo (castCoToCo (exprType rhs) co)) })
    
    649
    +             | isStableSource src -> return (unf { uf_tmpl = mkCastCo unf_rhs (mkSymCastCo (exprType rhs) co) })
    
    648 650
                _ -> mkLetUnfolding env top_lvl VanillaSrc work_id False work_rhs
    
    649 651
     
    
    650 652
     tryCastWorkerWrapper env _ _ bndr rhs  -- All other bindings
    
    ... ... @@ -1361,6 +1363,15 @@ simplCoercion env co
    1361 1363
         subst = getTCvSubst env
    
    1362 1364
         opts  = seOptCoercionOpts env
    
    1363 1365
     
    
    1366
    +simplCastCoercion :: SimplEnv -> InType -> InCastCoercion -> SimplM (OutType, OutCastCoercion)
    
    1367
    +simplCastCoercion env _   (CCoercion co)      = (\co -> (coercionLKind co, CCoercion co)) <$> simplCoercion env co
    
    1368
    +simplCastCoercion env tyL (ZCoercion tyR cos) = (,) <$> simplType env tyL <*> (ZCoercion <$> simplType env tyR <*> simplCoVars env cos)
    
    1369
    +simplCastCoercion env tyL ReflCastCo          = (,) <$> simplType env tyL <*> pure ReflCastCo
    
    1370
    +
    
    1371
    +simplCoVars :: SimplEnv -> CoVarSet -> SimplM CoVarSet
    
    1372
    +simplCoVars env covars = pure $ substCoVarSet (getTCvSubst env) covars
    
    1373
    +
    
    1374
    +
    
    1364 1375
     -----------------------------------
    
    1365 1376
     -- | Push a TickIt context outwards past applications and cases, as
    
    1366 1377
     -- long as this is a non-scoping tick, to let case and application
    
    ... ... @@ -1531,10 +1542,10 @@ rebuild_go env expr cont
    1531 1542
           Stop {}          -> return (emptyFloats env, expr)
    
    1532 1543
           TickIt t cont    -> rebuild_go env (mkTick t expr) cont
    
    1533 1544
           CastIt { sc_co = co, sc_opt = opt, sc_cont = cont }
    
    1534
    -        -> rebuild_go env (mkCast expr co') cont
    
    1545
    +        -> rebuild_go env (mkCastCo expr co') cont
    
    1535 1546
                -- NB: mkCast implements the (Coercion co |> g) optimisation
    
    1536 1547
             where
    
    1537
    -          co' = optOutCoercion env co opt
    
    1548
    +          co' = optOutCastCoercion env co opt
    
    1538 1549
     
    
    1539 1550
           Select { sc_bndr = bndr, sc_alts = alts, sc_env = se, sc_cont = cont }
    
    1540 1551
             -> rebuildCase (se `setInScopeFromE` env) expr bndr alts cont
    
    ... ... @@ -1663,6 +1674,12 @@ on each successive composition -- that's at least quadratic. So:
    1663 1674
     -}
    
    1664 1675
     
    
    1665 1676
     
    
    1677
    +optOutCastCoercion :: SimplEnvIS -> OutCastCoercion -> Bool -> OutCastCoercion
    
    1678
    +optOutCastCoercion env cco already_optimised = case cco of
    
    1679
    +    ReflCastCo   -> ReflCastCo
    
    1680
    +    CCoercion co -> CCoercion (optOutCoercion env co already_optimised)
    
    1681
    +    ZCoercion{}  -> cco
    
    1682
    +
    
    1666 1683
     optOutCoercion :: SimplEnvIS -> OutCoercion -> Bool -> OutCoercion
    
    1667 1684
     -- See Note [Avoid re-simplifying coercions]
    
    1668 1685
     optOutCoercion env co already_optimised
    
    ... ... @@ -1675,72 +1692,74 @@ optOutCoercion env co already_optimised
    1675 1692
     simplCast :: SimplEnv -> InExpr -> InCastCoercion -> SimplCont
    
    1676 1693
               -> SimplM (SimplFloats, OutExpr)
    
    1677 1694
     simplCast env body co0 cont0
    
    1678
    -  = do  { co1   <- {-#SCC "simplCast-simplCoercion" #-} simplCoercion env (castCoToCo (exprType body) co0) -- TODO better way?
    
    1695
    +  = do  { (tyL, co1) <- {-#SCC "simplCast-simplCoercion" #-} simplCastCoercion env (exprType body) co0
    
    1679 1696
             ; cont1 <- {-#SCC "simplCast-addCoerce" #-}
    
    1680
    -                   if isReflCo co1
    
    1697
    +                   if isReflCastCo co1
    
    1681 1698
                        then return cont0  -- See Note [Optimising reflexivity]
    
    1682
    -                   else addCoerce co1 True cont0
    
    1699
    +                   else addCoerce tyL co1 True cont0
    
    1683 1700
                             -- True <=> co1 is optimised
    
    1684 1701
             ; {-#SCC "simplCast-simplExprF" #-} simplExprF env body cont1 }
    
    1685 1702
       where
    
    1686 1703
     
    
    1687 1704
             -- If the first parameter is MRefl, then simplifying revealed a
    
    1688 1705
             -- reflexive coercion. Omit.
    
    1689
    -        addCoerceM :: MOutCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1690
    -        addCoerceM MRefl    _   cont = return cont
    
    1691
    -        addCoerceM (MCo co) opt cont = addCoerce co opt cont
    
    1692
    -
    
    1693
    -        addCoerce :: OutCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1694
    -        addCoerce co1 _ (CastIt { sc_co = co2, sc_cont = cont })  -- See Note [Optimising reflexivity]
    
    1695
    -          = addCoerce (mkTransCo co1 co2) False cont
    
    1706
    +        -- TODO: probably can simplify this further now?
    
    1707
    +        addCoerceM :: OutType -> OutCastCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1708
    +        addCoerceM _ ReflCastCo _   cont = return cont
    
    1709
    +        addCoerceM tyL co opt cont = addCoerce tyL co opt cont
    
    1710
    +
    
    1711
    +        -- Type tyL is the coercionLKind of the coercion
    
    1712
    +        addCoerce :: OutType -> OutCastCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1713
    +        addCoerce tyL co1 _ (CastIt { sc_co = co2, sc_cont = cont })  -- See Note [Optimising reflexivity]
    
    1714
    +          = addCoerce tyL (mkTransCastCo co1 co2) False cont
    
    1696 1715
                           -- False: (mkTransCo co1 co2) is not fully optimised
    
    1697 1716
                           -- See Note [Avoid re-simplifying coercions]
    
    1698 1717
     
    
    1699
    -        addCoerce co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
    
    1700
    -          | Just (arg_ty', m_co') <- pushCoTyArg co arg_ty
    
    1718
    +        addCoerce tyL co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_cont = tail })
    
    1719
    +          | Just (arg_ty', m_co') <- pushCastCoTyArg co arg_ty
    
    1701 1720
               = {-#SCC "addCoerce-pushCoTyArg" #-}
    
    1702
    -            do { tail' <- addCoerceM m_co' co_is_opt tail
    
    1721
    +            do { tail' <- addCoerceM hole_ty m_co' co_is_opt tail -- TODO is hole_ty right?
    
    1703 1722
                    ; return (ApplyToTy { sc_arg_ty  = arg_ty'
    
    1704 1723
                                        , sc_cont    = tail'
    
    1705
    -                                   , sc_hole_ty = coercionLKind co }) }
    
    1724
    +                                   , sc_hole_ty = tyL }) }
    
    1706 1725
                                             -- NB!  As the cast goes past, the
    
    1707 1726
                                             -- type of the hole changes (#16312)
    
    1708 1727
             -- (f |> co) e   ===>   (f (e |> co1)) |> co2
    
    1709 1728
             -- where   co :: (s1->s2) ~ (t1->t2)
    
    1710 1729
             --         co1 :: t1 ~ s1
    
    1711 1730
             --         co2 :: s2 ~ t2
    
    1712
    -        addCoerce co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    1731
    +        addCoerce tyL co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    1713 1732
                                                     , sc_dup = dup, sc_cont = tail
    
    1714 1733
                                                     , sc_hole_ty = fun_ty })
    
    1715 1734
               | not co_is_opt  -- pushCoValArg duplicates the coercion, so optimise first
    
    1716
    -          = addCoerce (optOutCoercion (zapSubstEnv env) co co_is_opt) True cont
    
    1735
    +          = addCoerce tyL (optOutCastCoercion (zapSubstEnv env) co co_is_opt) True cont
    
    1717 1736
     
    
    1718
    -          | Just (m_co1, m_co2) <- pushCoValArg co
    
    1737
    +          | Just (m_co1, m_co2) <- pushCastCoValArg fun_ty co -- TODO check fun_ty
    
    1719 1738
               = {-#SCC "addCoerce-pushCoValArg" #-}
    
    1720
    -            do { tail' <- addCoerceM m_co2 co_is_opt tail
    
    1721
    -               ; case m_co1 of {
    
    1722
    -                   MRefl -> return (cont { sc_cont = tail'
    
    1723
    -                                         , sc_hole_ty = coercionLKind co }) ;
    
    1739
    +            do { tail' <- addCoerceM (funResultTy fun_ty) m_co2 co_is_opt tail -- TODO check funResultTy fun_ty
    
    1740
    +               ; if isReflCastCo m_co1
    
    1741
    +                   then return (cont { sc_cont = tail'
    
    1742
    +                                         , sc_hole_ty = tyL }) ;
    
    1724 1743
                           -- See Note [Avoiding simplifying repeatedly]
    
    1725 1744
     
    
    1726
    -                   MCo co1 ->
    
    1745
    +                   else
    
    1727 1746
                 do { (dup', arg_se', arg') <- simplLazyArg env dup fun_ty Nothing arg_se arg
    
    1728 1747
                         -- When we build the ApplyTo we can't mix the OutCoercion
    
    1729 1748
                         -- 'co' with the InExpr 'arg', so we simplify
    
    1730 1749
                         -- to make it all consistent.  It's a bit messy.
    
    1731 1750
                         -- But it isn't a common case.
    
    1732 1751
                         -- Example of use: #995
    
    1733
    -               ; return (ApplyToVal { sc_arg  = mkCast arg' co1
    
    1752
    +               ; return (ApplyToVal { sc_arg  = mkCastCo arg' m_co1
    
    1734 1753
                                         , sc_env  = arg_se'
    
    1735 1754
                                         , sc_dup  = dup'
    
    1736 1755
                                         , sc_cont = tail'
    
    1737
    -                                    , sc_hole_ty = coercionLKind co }) } } }
    
    1756
    +                                    , sc_hole_ty = tyL }) } }
    
    1738 1757
     
    
    1739
    -        addCoerce co co_is_opt cont
    
    1740
    -          | isReflCo co = return cont  -- Having this at the end makes a huge
    
    1758
    +        addCoerce tyL co co_is_opt cont
    
    1759
    +          | isReflCastCo co = return cont  -- Having this at the end makes a huge
    
    1741 1760
                                            -- difference in T12227, for some reason
    
    1742 1761
                                            -- See Note [Optimising reflexivity]
    
    1743
    -          | otherwise = return (CastIt { sc_co = co, sc_opt = co_is_opt, sc_cont = cont })
    
    1762
    +          | otherwise = return (CastIt { sc_co = co, sc_hole_ty = tyL, sc_opt = co_is_opt, sc_cont = cont })
    
    1744 1763
     
    
    1745 1764
     simplLazyArg :: SimplEnvIS              -- ^ Used only for its InScopeSet
    
    1746 1765
                  -> DupFlag
    
    ... ... @@ -3595,9 +3614,9 @@ addAltUnfoldings env case_bndr bndr_swap con_app
    3595 3614
         -- See Note [Add unfolding for scrutinee]
    
    3596 3615
         env2 | DoBinderSwap v mco <- bndr_swap
    
    3597 3616
              = addBinderUnfolding env1 v $
    
    3598
    -              if isReflMCo mco  -- isReflMCo: avoid calling mk_simple_unf
    
    3617
    +              if isReflCastCo mco  -- isReflCastCo: avoid calling mk_simple_unf
    
    3599 3618
                   then con_app_unf  --            twice in the common case
    
    3600
    -              else mk_simple_unf (mkCastMCo con_app mco)
    
    3619
    +              else mk_simple_unf (mkCastCo con_app mco)
    
    3601 3620
     
    
    3602 3621
              | otherwise = env1
    
    3603 3622
     
    
    ... ... @@ -3865,9 +3884,10 @@ mkDupableContWithDmds env _ cont
    3865 3884
     
    
    3866 3885
     mkDupableContWithDmds _ _ (Stop {}) = panic "mkDupableCont"     -- Handled by previous eqn
    
    3867 3886
     
    
    3868
    -mkDupableContWithDmds env dmds (CastIt { sc_co = co, sc_opt = opt, sc_cont = cont })
    
    3887
    +mkDupableContWithDmds env dmds (CastIt { sc_co = co, sc_hole_ty = ty, sc_opt = opt, sc_cont = cont })
    
    3869 3888
       = do  { (floats, cont') <- mkDupableContWithDmds env dmds cont
    
    3870
    -        ; return (floats, CastIt { sc_co = optOutCoercion env co opt
    
    3889
    +        ; return (floats, CastIt { sc_co = optOutCastCoercion env co opt
    
    3890
    +                                 , sc_hole_ty = ty
    
    3871 3891
                                      , sc_opt = True, sc_cont = cont' }) }
    
    3872 3892
                      -- optOutCoercion: see Note [Avoid re-simplifying coercions]
    
    3873 3893
     
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -52,7 +52,7 @@ import GHC.Core.Opt.Simplify.Inline( smallEnoughToInline )
    52 52
     import GHC.Core.Opt.Stats ( Tick(..) )
    
    53 53
     import qualified GHC.Core.Subst
    
    54 54
     import GHC.Core.Ppr
    
    55
    -import GHC.Core.TyCo.Ppr ( pprParendType )
    
    55
    +import GHC.Core.TyCo.Ppr ( pprParendType, pprCastCo )
    
    56 56
     import GHC.Core.FVs
    
    57 57
     import GHC.Core.Utils
    
    58 58
     import GHC.Core.Opt.Arity
    
    ... ... @@ -162,8 +162,9 @@ data SimplCont
    162 162
     
    
    163 163
     
    
    164 164
       | CastIt              -- (CastIt co K)[e] = K[ e `cast` co ]
    
    165
    -      { sc_co   :: OutCoercion  -- The coercion simplified
    
    165
    +      { sc_co   :: OutCastCoercion  -- The coercion simplified
    
    166 166
                                     -- Invariant: never an identity coercion
    
    167
    +      , sc_hole_ty :: OutType   -- LHS kind of sc_co
    
    167 168
           , sc_opt  :: Bool         -- True <=> sc_co has had optCoercion applied to it
    
    168 169
                                     --      See Note [Avoid re-simplifying coercions]
    
    169 170
                                     --      in GHC.Core.Opt.Simplify.Iteration
    
    ... ... @@ -277,7 +278,7 @@ instance Outputable SimplCont where
    277 278
         where
    
    278 279
           pps = [ppr interesting] ++ [ppr eval_sd | eval_sd /= topSubDmd]
    
    279 280
       ppr (CastIt { sc_co = co, sc_cont = cont })
    
    280
    -    = (text "CastIt" <+> pprOptCo co) $$ ppr cont
    
    281
    +    = (text "CastIt" <+> pprCastCo co) $$ ppr cont
    
    281 282
       ppr (TickIt t cont)
    
    282 283
         = (text "TickIt" <+> ppr t) $$ ppr cont
    
    283 284
       ppr (ApplyToTy  { sc_arg_ty = ty, sc_cont = cont })
    
    ... ... @@ -474,7 +475,7 @@ contResultType (TickIt _ k) = contResultType k
    474 475
     contHoleType :: SimplCont -> OutType
    
    475 476
     contHoleType (Stop ty _ _)                    = ty
    
    476 477
     contHoleType (TickIt _ k)                     = contHoleType k
    
    477
    -contHoleType (CastIt { sc_co = co })          = coercionLKind co
    
    478
    +contHoleType (CastIt { sc_hole_ty = ty })     = ty
    
    478 479
     contHoleType (StrictBind { sc_bndr = b, sc_dup = dup, sc_env = se })
    
    479 480
       = perhapsSubstTy dup se (idType b)
    
    480 481
     contHoleType (StrictArg  { sc_fun_ty = ty })  = funArgTy ty
    
    ... ... @@ -1896,7 +1897,7 @@ rebuildLam env bndrs@(bndr:_) body cont
    1896 1897
           | -- Note [Casts and lambdas]
    
    1897 1898
             seCastSwizzle env
    
    1898 1899
           , not (any bad bndrs)
    
    1899
    -      = mkCast (mk_lams bndrs body) (mkPiCos Representational bndrs (castCoToCo (exprType body) co))
    
    1900
    +      = mkCastCo (mk_lams bndrs body) (mkPiCastCos Representational bndrs co)
    
    1900 1901
           where
    
    1901 1902
             co_vars  = tyCoVarsOfCastCo co
    
    1902 1903
             bad bndr = isCoVar bndr && bndr `elemVarSet` co_vars
    

  • compiler/GHC/Core/Opt/SpecConstr.hs
    ... ... @@ -1120,7 +1120,7 @@ extendCaseBndrs env scrut case_bndr con alt_bndrs
    1120 1120
      where
    
    1121 1121
        live_case_bndr = not (isDeadBinder case_bndr)
    
    1122 1122
        env1 | DoBinderSwap v mco <- scrutOkForBinderSwap scrut
    
    1123
    -        , isReflMCo mco  = extendValEnv env v cval
    
    1123
    +        , isReflCastCo mco = extendValEnv env v cval
    
    1124 1124
             | otherwise      = env  -- See Note [Add scrutinee to ValueEnv too]
    
    1125 1125
        env2 | live_case_bndr = extendValEnv env1 case_bndr cval
    
    1126 1126
             | otherwise      = env1
    

  • compiler/GHC/Core/Rules.hs
    ... ... @@ -52,13 +52,14 @@ import GHC.Core.FVs ( exprFreeVars, bindFreeVars
    52 52
                               , rulesFreeVarsDSet, orphNamesOfExprs )
    
    53 53
     import GHC.Core.Utils     ( exprType, mkTick, mkTicks
    
    54 54
                               , stripTicksTopT, stripTicksTopE
    
    55
    -                          , isJoinBind, mkCastMCo )
    
    55
    +                          , isJoinBind, mkCastCo )
    
    56 56
     import GHC.Core.Ppr       ( pprRules )
    
    57 57
     import GHC.Core.Unify as Unify ( ruleMatchTyKiX )
    
    58 58
     import GHC.Core.Type as Type
    
    59 59
        ( Type, extendTvSubst, extendCvSubst
    
    60 60
        , substTy, getTyVar_maybe )
    
    61 61
     import GHC.Core.TyCo.Ppr( pprParendType )
    
    62
    +import GHC.Core.TyCo.FVs ( tyCoFVsOfCastCoercion )
    
    62 63
     import GHC.Core.Coercion as Coercion
    
    63 64
     import GHC.Core.Tidy     ( tidyRules )
    
    64 65
     import GHC.Core.Map.Expr ( eqCoreExpr )
    
    ... ... @@ -815,7 +816,7 @@ match_exprs :: HasDebugCallStack
    815 816
     match_exprs _ subst [] _
    
    816 817
       = Just subst
    
    817 818
     match_exprs renv subst (e1:es1) (e2:es2)
    
    818
    -  = do { subst' <- match renv subst e1 e2 MRefl
    
    819
    +  = do { subst' <- match renv subst e1 e2 ReflCastCo
    
    819 820
            ; match_exprs renv subst' es1 es2 }
    
    820 821
     match_exprs _ _ _ _ = Nothing
    
    821 822
     
    
    ... ... @@ -1065,7 +1066,7 @@ match :: HasDebugCallStack
    1065 1066
           -> RuleSubst              -- Substitution applies to template only
    
    1066 1067
           -> CoreExpr               -- Template
    
    1067 1068
           -> CoreExpr               -- Target
    
    1068
    -      -> MCoercion
    
    1069
    +      -> CastCoercion
    
    1069 1070
           -> Maybe RuleSubst
    
    1070 1071
     
    
    1071 1072
     -- Postcondition (TypeInv): if matching succeeds, then
    
    ... ... @@ -1102,8 +1103,8 @@ match renv subst (Type ty1) (Type ty2) _mco
    1102 1103
     
    
    1103 1104
     ------------------------ Coercions ---------------------
    
    1104 1105
     -- See Note [Coercion arguments] for why this isn't really right
    
    1105
    -match renv subst (Coercion co1) (Coercion co2) MRefl
    
    1106
    -  = match_co renv subst co1 co2
    
    1106
    +match renv subst (Coercion co1) (Coercion co2) ReflCastCo
    
    1107
    +  = match_co renv subst (CCoercion co1) (CCoercion co2) -- TODO should probably have match_cast_co and match_co separately?
    
    1107 1108
       -- The MCo case corresponds to matching  co ~ (co2 |> co3)
    
    1108 1109
       -- and I have no idea what to do there -- or even if it can occur
    
    1109 1110
       -- Failing seems the simplest thing to do; it's certainly safe.
    
    ... ... @@ -1114,23 +1115,23 @@ match renv subst (Coercion co1) (Coercion co2) MRefl
    1114 1115
     --     Note [Cancel reflexive casts]
    
    1115 1116
     
    
    1116 1117
     match renv subst e1 (Cast e2 co2) mco
    
    1117
    -  = match renv subst e1 e2 (checkReflexiveMCo (mkTransMCoR (castCoToCo (exprType e2) co2) mco))
    
    1118
    +  = match renv subst e1 e2 (checkReflexiveCastCo (exprType e2) (mkTransCastCo co2 mco))
    
    1118 1119
         -- checkReflexiveMCo: cancel casts if possible
    
    1119 1120
         -- This is important: see Note [Cancel reflexive casts]
    
    1120 1121
     
    
    1121 1122
     match renv subst (Cast e1 co1) e2 mco
    
    1122
    -  = matchTemplateCast renv subst e1 (castCoToCo (exprType e1) co1) e2 mco
    
    1123
    +  = matchTemplateCast renv subst e1 co1 e2 mco
    
    1123 1124
     
    
    1124 1125
     ------------------------ Literals ---------------------
    
    1125 1126
     match _ subst (Lit lit1) (Lit lit2) mco
    
    1126 1127
       | lit1 == lit2
    
    1127
    -  = assertPpr (isReflMCo mco) (ppr mco) $
    
    1128
    +  = assertPpr (isReflCastCo mco) (ppr mco) $
    
    1128 1129
         Just subst
    
    1129 1130
     
    
    1130 1131
     ------------------------ Variables ---------------------
    
    1131 1132
     -- The Var case follows closely what happens in GHC.Core.Unify.match
    
    1132 1133
     match renv subst (Var v1) e2 mco
    
    1133
    -  = match_var renv subst v1 (mkCastMCo e2 mco)
    
    1134
    +  = match_var renv subst v1 (mkCastCo e2 mco)
    
    1134 1135
     
    
    1135 1136
     match renv subst e1 (Var v2) mco  -- Note [Expanding variables]
    
    1136 1137
       | not (inRnEnvR rn_env v2)      -- Note [Do not expand locally-bound variables]
    
    ... ... @@ -1148,7 +1149,7 @@ match renv subst e1 (Var v2) mco -- Note [Expanding variables]
    1148 1149
     -- See Note [Matching higher order patterns]
    
    1149 1150
     match renv@(RV { rv_tmpls = tmpls, rv_lcl = rn_env })
    
    1150 1151
           subst  e1@App{} e2
    
    1151
    -      MRefl               -- Like the App case we insist on Refl here
    
    1152
    +      ReflCastCo          -- Like the App case we insist on Refl here
    
    1152 1153
                               -- See Note [Casts in the target]
    
    1153 1154
       | (Var f, args) <- collectArgs e1
    
    1154 1155
       , let f' = rnOccL rn_env f   -- See similar rnOccL in match_var
    
    ... ... @@ -1308,9 +1309,9 @@ Two wrinkles:
    1308 1309
     --     (e1 e2) ~ (d1 d2) |> co
    
    1309 1310
     -- See Note [Cancel reflexive casts]: in the Cast equations for 'match'
    
    1310 1311
     -- we aggressively ensure that if MCo is reflective, it really is MRefl.
    
    1311
    -match renv subst (App f1 a1) (App f2 a2) MRefl
    
    1312
    -  = do  { subst' <- match renv subst f1 f2 MRefl
    
    1313
    -        ; match renv subst' a1 a2 MRefl }
    
    1312
    +match renv subst (App f1 a1) (App f2 a2) ReflCastCo
    
    1313
    +  = do  { subst' <- match renv subst f1 f2 ReflCastCo
    
    1314
    +        ; match renv subst' a1 a2 ReflCastCo }
    
    1314 1315
     
    
    1315 1316
     ------------------------ Float lets ---------------------
    
    1316 1317
     match renv subst e1 (Let bind e2) mco
    
    ... ... @@ -1336,7 +1337,7 @@ match renv subst e1 (Let bind e2) mco
    1336 1337
     
    
    1337 1338
     ------------------------  Lambdas ---------------------
    
    1338 1339
     match renv subst (Lam x1 e1) e2 mco
    
    1339
    -  | let casted_e2 = mkCastMCo e2 mco
    
    1340
    +  | let casted_e2 = mkCastCo e2 mco
    
    1340 1341
             in_scope = extendInScopeSetSet (rnInScopeSet (rv_lcl renv))
    
    1341 1342
                                            (exprFreeVars casted_e2)
    
    1342 1343
             in_scope_env = ISE in_scope (rv_unf renv)
    
    ... ... @@ -1349,7 +1350,7 @@ match renv subst (Lam x1 e1) e2 mco
    1349 1350
         -- See Note [Lambdas in the template]
    
    1350 1351
       = let renv'  = rnMatchBndr2 renv x1 x2
    
    1351 1352
             subst' = subst { rs_binds = rs_binds subst . flip (foldr mkTick) ts }
    
    1352
    -    in  match renv' subst' e1 e2' MRefl
    
    1353
    +    in  match renv' subst' e1 e2' ReflCastCo
    
    1353 1354
     
    
    1354 1355
     match renv subst e1 e2@(Lam {}) mco
    
    1355 1356
       | Just (renv', e2') <- eta_reduce renv e2  -- See Note [Eta reduction in the target]
    
    ... ... @@ -1400,7 +1401,7 @@ match renv (tv_subst, id_subst, binds) e1
    1400 1401
     
    
    1401 1402
     match renv subst (Case e1 x1 ty1 alts1) (Case e2 x2 ty2 alts2) mco
    
    1402 1403
       = do  { subst1 <- match_ty renv subst ty1 ty2
    
    1403
    -        ; subst2 <- match renv subst1 e1 e2 MRefl
    
    1404
    +        ; subst2 <- match renv subst1 e1 e2 ReflCastCo
    
    1404 1405
             ; let renv' = rnMatchBndr2 renv x1 x2
    
    1405 1406
             ; match_alts renv' subst2 alts1 alts2 mco   -- Alts are both sorted
    
    1406 1407
             }
    
    ... ... @@ -1503,29 +1504,29 @@ Hence
    1503 1504
     -------------
    
    1504 1505
     matchTemplateCast
    
    1505 1506
         :: RuleMatchEnv -> RuleSubst
    
    1506
    -    -> CoreExpr -> Coercion
    
    1507
    -    -> CoreExpr -> MCoercion
    
    1507
    +    -> CoreExpr -> CastCoercion
    
    1508
    +    -> CoreExpr -> CastCoercion
    
    1508 1509
         -> Maybe RuleSubst
    
    1509 1510
     matchTemplateCast renv subst e1 co1 e2 mco
    
    1510 1511
       | isEmptyVarSet $ fvVarSet $
    
    1511 1512
         filterFV (`elemVarSet` rv_tmpls renv) $    -- Check that the coercion does not
    
    1512
    -    tyCoFVsOfCo substed_co                     -- mention any of the template variables
    
    1513
    +    tyCoFVsOfCastCoercion substed_co                     -- mention any of the template variables
    
    1513 1514
       = -- This is the good path
    
    1514 1515
         -- See Note [Casts in the template] wrinkle (CT0)
    
    1515
    -    match renv subst e1 e2 (checkReflexiveMCo (mkTransMCoL mco (mkSymCo substed_co)))
    
    1516
    +    match renv subst e1 e2 (checkReflexiveCastCo substed_ty (mkTransCastCo mco (mkSymCastCo substed_ty substed_co)))
    
    1517
    +    -- AMG TODO: should be able to make checkReflexiveCastCo cheaper here?
    
    1516 1518
     
    
    1517 1519
       | otherwise
    
    1518 1520
       = -- This is the Deeply Suspicious Path
    
    1519 1521
         -- See Note [Casts in the template]
    
    1520
    -    do { let co2 = case mco of
    
    1521
    -                     MRefl   -> mkRepReflCo (exprType e2)
    
    1522
    -                     MCo co2 -> co2
    
    1522
    +    do { let co2 = mco
    
    1523 1523
            ; subst1 <- match_co renv subst co1 co2
    
    1524 1524
              -- If match_co succeeds, then (exprType e1) = (exprType e2)
    
    1525
    -         -- Hence the MRefl in the next line
    
    1526
    -       ; match renv subst1 e1 e2 MRefl }
    
    1525
    +         -- Hence the ReflCastCo in the next line
    
    1526
    +       ; match renv subst1 e1 e2 ReflCastCo }
    
    1527 1527
       where
    
    1528
    -    substed_co = substCo current_subst co1
    
    1528
    +    substed_ty = substTy current_subst (exprType e1)
    
    1529
    +    substed_co = substCastCo current_subst co1
    
    1529 1530
     
    
    1530 1531
         current_subst :: Subst
    
    1531 1532
         current_subst = mkTCvSubst (rnInScopeSet (rv_lcl renv))
    
    ... ... @@ -1538,8 +1539,8 @@ matchTemplateCast renv subst e1 co1 e2 mco
    1538 1539
     
    
    1539 1540
     match_co :: RuleMatchEnv
    
    1540 1541
              -> RuleSubst
    
    1541
    -         -> Coercion
    
    1542
    -         -> Coercion
    
    1542
    +         -> CastCoercion
    
    1543
    +         -> CastCoercion
    
    1543 1544
              -> Maybe RuleSubst
    
    1544 1545
     -- We only match if the template is a coercion variable or Refl:
    
    1545 1546
     --   see Note [Casts in the template]
    
    ... ... @@ -1548,7 +1549,7 @@ match_co :: RuleMatchEnv
    1548 1549
     -- But if match_co succeeds, it /is/ guaranteed that
    
    1549 1550
     --     coercionKind (subst template) = coercionKind target
    
    1550 1551
     
    
    1551
    -match_co renv subst co1 co2
    
    1552
    +match_co renv subst (CCoercion co1) (CCoercion co2)
    
    1552 1553
       | Just cv <- getCoVar_maybe co1
    
    1553 1554
       = match_var renv subst cv (Coercion co2)
    
    1554 1555
     
    
    ... ... @@ -1563,6 +1564,7 @@ match_co renv subst co1 co2
    1563 1564
     
    
    1564 1565
       | otherwise
    
    1565 1566
       = Nothing
    
    1567
    +match_co renv subst _ _ = Nothing -- TODO: support non-CCoercions in rule matcher
    
    1566 1568
     
    
    1567 1569
     -------------
    
    1568 1570
     rnMatchBndr2 :: RuleMatchEnv -> Var -> Var -> RuleMatchEnv
    
    ... ... @@ -1575,7 +1577,7 @@ rnMatchBndr2 renv x1 x2
    1575 1577
     match_alts :: RuleMatchEnv
    
    1576 1578
                -> RuleSubst
    
    1577 1579
                -> [CoreAlt]                 -- Template
    
    1578
    -           -> [CoreAlt] -> MCoercion    -- Target
    
    1580
    +           -> [CoreAlt] -> CastCoercion    -- Target
    
    1579 1581
                -> Maybe RuleSubst
    
    1580 1582
     match_alts _ subst [] [] _
    
    1581 1583
       = return subst
    
    ... ... @@ -2018,7 +2020,7 @@ ruleAppCheck_help env fn args rules
    2018 2020
               mismatches   = [i | (rule_arg, (arg,i)) <- rule_args `zip` i_args,
    
    2019 2021
                                   not (isJust (match_fn rule_arg arg))]
    
    2020 2022
     
    
    2021
    -          match_fn rule_arg arg = match renv emptyRuleSubst rule_arg arg MRefl
    
    2023
    +          match_fn rule_arg arg = match renv emptyRuleSubst rule_arg arg ReflCastCo
    
    2022 2024
                     where
    
    2023 2025
                       renv = RV { rv_lcl   = mkRnEnv2 in_scope
    
    2024 2026
                                 , rv_tmpls = mkVarSet rule_bndrs
    

  • compiler/GHC/Core/SimpleOpt.hs
    ... ... @@ -31,8 +31,8 @@ import GHC.Core.Unfold.Make
    31 31
     import GHC.Core.Make ( FloatBind(..), mkWildValBinder )
    
    32 32
     import GHC.Core.Opt.OccurAnal( occurAnalyseExpr, occurAnalysePgm, zapLambdaBndrs )
    
    33 33
     import GHC.Core.DataCon
    
    34
    -import GHC.Core.Coercion.Opt ( optCoercion, OptCoercionOpts (..) )
    
    35
    -import GHC.Core.Type hiding ( substTy, extendTvSubst, extendCvSubst, extendTvSubstList
    
    34
    +import GHC.Core.Coercion.Opt ( optCoercion, optCastCoercion, OptCoercionOpts (..) )
    
    35
    +import GHC.Core.Type hiding ( extendTvSubst, extendCvSubst, extendTvSubstList
    
    36 36
                                 , isInScope, substTyVarBndr, cloneTyVarBndr )
    
    37 37
     import GHC.Core.Predicate( isCoVarType )
    
    38 38
     import GHC.Core.Coercion hiding ( substCo, substCoVarBndr )
    
    ... ... @@ -213,7 +213,7 @@ simpleOptPgm opts this_mod binds rules =
    213 213
     ----------------------
    
    214 214
     type SimpleClo = (SimpleOptEnv, InExpr)
    
    215 215
     
    
    216
    -data SimpleContItem = ApplyToArg SimpleClo | CastIt OutCoercion
    
    216
    +data SimpleContItem = ApplyToArg SimpleClo | CastIt OutCastCoercion
    
    217 217
     
    
    218 218
     instance Outputable SimpleContItem where
    
    219 219
       ppr (ApplyToArg (_, arg)) = text "ARG" <+> ppr arg
    
    ... ... @@ -402,7 +402,7 @@ simple_app env e0@(Lam {}) as0@(_:_)
    402 402
           = rebuild_app env (simple_opt_expr env e) as
    
    403 403
     
    
    404 404
         do_beta env (Cast e co) as =
    
    405
    -      do_beta env e (add_cast env (castCoToCo (exprType e) co) as)  -- TODO eliminate castCoToCo?
    
    405
    +      do_beta env e (add_cast env (exprType e) co as)
    
    406 406
     
    
    407 407
         do_beta env body as
    
    408 408
           = simple_app env body as
    
    ... ... @@ -450,21 +450,21 @@ simple_app env (Let bind body) args
    450 450
               expr' = Let bind' (simple_opt_expr env' body)
    
    451 451
     
    
    452 452
     simple_app env (Cast e co) as
    
    453
    -  = simple_app env e (add_cast env (castCoToCo (exprType e) co) as) -- TODO eliminate castCoToCo?
    
    453
    +  = simple_app env e (add_cast env (exprType e) co as)
    
    454 454
     
    
    455 455
     simple_app env e as
    
    456 456
       = rebuild_app env (simple_opt_expr env e) as
    
    457 457
     
    
    458
    -add_cast :: SimpleOptEnv -> InCoercion -> [SimpleContItem] -> [SimpleContItem]
    
    459
    -add_cast env co1 as
    
    460
    -  | isReflCo co1'
    
    458
    +add_cast :: SimpleOptEnv -> InType -> InCastCoercion -> [SimpleContItem] -> [SimpleContItem]
    
    459
    +add_cast env tyL co1 as
    
    460
    +  | isReflCastCo co1'
    
    461 461
       = as
    
    462 462
       | otherwise
    
    463 463
       = case as of
    
    464
    -      CastIt co2:rest -> CastIt (co1' `mkTransCo` co2):rest
    
    464
    +      CastIt co2:rest -> CastIt (co1' `mkTransCastCo` co2):rest
    
    465 465
           _               -> CastIt co1':as
    
    466 466
       where
    
    467
    -    co1' = optCoercion (so_co_opts (soe_opts env)) (soe_subst env) co1
    
    467
    +    co1' = optCastCoercion (so_co_opts (soe_opts env)) (soe_subst env) tyL co1
    
    468 468
     
    
    469 469
     rebuild_app :: HasDebugCallStack
    
    470 470
                 => SimpleOptEnv -> OutExpr -> [SimpleContItem] -> OutExpr
    
    ... ... @@ -473,7 +473,7 @@ rebuild_app env fun args = foldl mk_app fun args
    473 473
         in_scope = soeInScope env
    
    474 474
         mk_app out_fun = \case
    
    475 475
           ApplyToArg arg -> App out_fun (simple_opt_clo in_scope arg)
    
    476
    -      CastIt co      -> mk_cast out_fun (CCoercion co)
    
    476
    +      CastIt co      -> mk_cast out_fun co
    
    477 477
     
    
    478 478
     {- Note [Desugaring unlifted newtypes]
    
    479 479
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -1340,7 +1340,7 @@ data-con wrappers, and that cure would be worse than the disease.
    1340 1340
     This Note exists solely to document the problem.
    
    1341 1341
     -}
    
    1342 1342
     
    
    1343
    -data ConCont = CC [CoreExpr] MCoercion
    
    1343
    +data ConCont = CC [CoreExpr] CastCoercion
    
    1344 1344
                       -- Substitution already applied
    
    1345 1345
     
    
    1346 1346
     -- | Returns @Just ([b1..bp], dc, [t1..tk], [x1..xn])@ if the argument
    
    ... ... @@ -1362,7 +1362,7 @@ exprIsConApp_maybe :: HasDebugCallStack
    1362 1362
                        => InScopeEnv -> CoreExpr
    
    1363 1363
                        -> Maybe (InScopeSet, [FloatBind], DataCon, [Type], [CoreExpr])
    
    1364 1364
     exprIsConApp_maybe ise@(ISE in_scope id_unf) expr
    
    1365
    -  = go (Left in_scope) [] expr (CC [] MRefl)
    
    1365
    +  = go (Left in_scope) [] expr (CC [] ReflCastCo)
    
    1366 1366
       where
    
    1367 1367
         go :: Either InScopeSet Subst
    
    1368 1368
                  -- Left in-scope  means "empty substitution"
    
    ... ... @@ -1375,10 +1375,10 @@ exprIsConApp_maybe ise@(ISE in_scope id_unf) expr
    1375 1375
         go subst floats (Tick t expr) cont
    
    1376 1376
            | not (tickishIsCode t) = go subst floats expr cont
    
    1377 1377
     
    
    1378
    -    go subst floats (Cast expr co1) (CC args m_co2)
    
    1379
    -       | Just (args', m_co1') <- pushCoArgs (subst_co subst (castCoToCo (exprType expr) co1)) args
    
    1378
    +    go subst floats (Cast expr co1) (CC args m_co2) -- TODO: is the subst_ty below needed?
    
    1379
    +       | Just (args', m_co1') <- pushCoArgs (subst_ty subst (exprType expr)) (subst_cast_co subst co1) args
    
    1380 1380
                 -- See Note [Push coercions in exprIsConApp_maybe]
    
    1381
    -       = go subst floats expr (CC args' (m_co1' `mkTransMCo` m_co2))
    
    1381
    +       = go subst floats expr (CC args' (m_co1' `mkTransCastCo` m_co2))
    
    1382 1382
     
    
    1383 1383
         go subst floats (App fun arg) (CC args mco)
    
    1384 1384
            | let arg_type = exprType arg
    
    ... ... @@ -1515,6 +1515,12 @@ exprIsConApp_maybe ise@(ISE in_scope id_unf) expr
    1515 1515
         subst_co (Left {}) co = co
    
    1516 1516
         subst_co (Right s) co = GHC.Core.Subst.substCo s co
    
    1517 1517
     
    
    1518
    +    subst_cast_co (Left {}) co = co
    
    1519
    +    subst_cast_co (Right s) co = substCastCo s co
    
    1520
    +
    
    1521
    +    subst_ty (Left {}) ty = ty
    
    1522
    +    subst_ty (Right s) ty = substTy s ty
    
    1523
    +
    
    1518 1524
         subst_expr (Left {}) e = e
    
    1519 1525
         subst_expr (Right s) e = substExpr s e
    
    1520 1526
     
    
    ... ... @@ -1565,7 +1571,7 @@ exprIsConApp_maybe ise@(ISE in_scope id_unf) expr
    1565 1571
                      (right, _, _) -> pprPanic "case_bind did not preserve Left" (ppr in_scope $$ ppr arg $$ ppr right)
    
    1566 1572
     
    
    1567 1573
     -- See Note [exprIsConApp_maybe on literal strings]
    
    1568
    -dealWithStringLiteral :: Var -> BS.ByteString -> MCoercion
    
    1574
    +dealWithStringLiteral :: Var -> BS.ByteString -> CastCoercion
    
    1569 1575
                           -> Maybe (DataCon, [Type], [CoreExpr])
    
    1570 1576
     
    
    1571 1577
     -- This is not possible with user-supplied empty literals, GHC.Core.Make.mkStringExprFS
    
    ... ... @@ -1666,13 +1672,12 @@ exprIsLambda_maybe ise (Tick t e)
    1666 1672
         = Just (x, e, t:ts)
    
    1667 1673
     
    
    1668 1674
     -- Also possible: A casted lambda. Push the coercion inside
    
    1669
    -exprIsLambda_maybe ise@(ISE in_scope_set _) (Cast casted_e cco)
    
    1675
    +exprIsLambda_maybe ise@(ISE in_scope_set _) (Cast casted_e co)
    
    1670 1676
         | Just (x, e,ts) <- exprIsLambda_maybe ise casted_e
    
    1671 1677
         -- Only do value lambdas.
    
    1672 1678
         -- this implies that x is not in scope in gamma (makes this code simpler)
    
    1673 1679
         , not (isTyVar x) && not (isCoVar x)
    
    1674
    -    , let co = castCoToCo (exprType casted_e) cco
    
    1675
    -    , assert (not $ x `elemVarSet` tyCoVarsOfCo co) True
    
    1680
    +    , assert (not $ x `elemVarSet` tyCoVarsOfCastCo co) True
    
    1676 1681
         , Just (x',e') <- pushCoercionIntoLambda (mkEmptySubst in_scope_set) x e co
    
    1677 1682
         , let res = Just (x',e',ts)
    
    1678 1683
         = --pprTrace "exprIsLambda_maybe:Cast" (vcat [ppr casted_e,ppr co,ppr res)])
    

  • compiler/GHC/Core/TyCo/FVs.hs
    ... ... @@ -21,7 +21,7 @@ module GHC.Core.TyCo.FVs
    21 21
             shallowCoVarsOfCo, shallowCoVarsOfCos, shallowCoVarsOfCastCo,
    
    22 22
             tyCoVarsOfCastCoercionDSet,
    
    23 23
             tyCoVarsOfCoDSet,
    
    24
    -        tyCoFVsOfCo, tyCoFVsOfCos, tyCoFVsOfCoVarSet,
    
    24
    +        tyCoFVsOfCo, tyCoFVsOfCos, tyCoFVsOfCoVarSet, tyCoFVsOfCastCoercion,
    
    25 25
             tyCoVarsOfCoList,
    
    26 26
             coVarsOfCoDSet, coVarsOfCosDSet,
    
    27 27
     
    

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -22,7 +22,7 @@ module GHC.Core.Utils (
    22 22
     
    
    23 23
             -- * Properties of expressions
    
    24 24
             exprType, coreAltType, coreAltsType,
    
    25
    -        mkLamType, mkLamTypes,
    
    25
    +        mkLamType, mkLamTypes, mkPiMCos,
    
    26 26
             mkFunctionType,
    
    27 27
             exprIsTrivial, getIdFromTrivialExpr, getIdFromTrivialExpr_maybe,
    
    28 28
             trivial_expr_fold,
    
    ... ... @@ -188,6 +188,12 @@ mkLamType v body_ty
    188 188
     
    
    189 189
     mkLamTypes vs ty = foldr mkLamType ty vs
    
    190 190
     
    
    191
    +mkPiMCos :: [Var] -> CastCoercion -> CastCoercion
    
    192
    +mkPiMCos _ ReflCastCo = ReflCastCo
    
    193
    +mkPiMCos vs (CCoercion co) = CCoercion (mkPiCos Representational vs co)
    
    194
    +mkPiMCos vs (ZCoercion ty cos) = ZCoercion (mkLamTypes vs ty) cos
    
    195
    +
    
    196
    +
    
    191 197
     {-
    
    192 198
     Note [Type bindings]
    
    193 199
     ~~~~~~~~~~~~~~~~~~~~