Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
c5a8bb9f
by Simon Peyton Jones at 2026-10-31T09:20:34-04:00
-
ab49b1d2
by Simon Peyton Jones at 2026-10-31T09:20:34-04:00
-
6efe4ba3
by Simon Peyton Jones at 2026-10-31T09:20:34-04:00
-
3b60ae7e
by Simon Peyton Jones at 2026-10-31T09:20:34-04:00
15 changed files:
- + changelog.d/T27994
- compiler/GHC/Core/Coercion/Axiom.hs
- compiler/GHC/Core/Predicate.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Tc/Instance/Family.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Types/Var/Env.hs
- + testsuite/tests/typecheck/should_compile/T27994.hs
- + testsuite/tests/typecheck/should_compile/T27994a.hs
- + testsuite/tests/typecheck/should_compile/T27994b.hs
- testsuite/tests/typecheck/should_compile/all.T
Changes:
| 1 | +section: compiler
|
|
| 2 | +issues: #27994
|
|
| 3 | +mrs: !16842
|
|
| 4 | +synopsis:
|
|
| 5 | + Fix a compiler Lint error in a heavily kind-polymorphic program
|
|
| 6 | +description:
|
|
| 7 | + There was a subtle bug deep in the code for computing functional dependencies for type families. |
| ... | ... | @@ -277,8 +277,8 @@ data CoAxBranch |
| 277 | 277 | -- See Note [CoAxBranch type variables]
|
| 278 | 278 | , cab_eta_tvs :: [TyVar]
|
| 279 | 279 | -- ^ Eta-reduced tyvars
|
| 280 | - -- cab_tvs and cab_lhs may be eta-reduced; see
|
|
| 281 | - -- Note [Eta reduction for data families]
|
|
| 280 | + -- For a data family (only) cab_tvs and cab_lhs may be eta-reduced
|
|
| 281 | + -- See Note [Eta reduction for data families]
|
|
| 282 | 282 | , cab_cvs :: [CoVar]
|
| 283 | 283 | -- ^ Bound coercion variables
|
| 284 | 284 | -- Always empty, for now.
|
| ... | ... | @@ -286,8 +286,14 @@ data CoAxBranch |
| 286 | 286 | -- in GHC.Tc.TyCl
|
| 287 | 287 | , cab_roles :: [Role]
|
| 288 | 288 | -- ^ See Note [CoAxBranch roles]
|
| 289 | + |
|
| 289 | 290 | , cab_lhs :: [Type]
|
| 290 | 291 | -- ^ Type patterns to match against
|
| 292 | + -- For a data family `cab_lhs` may be shorter than the arity
|
|
| 293 | + -- of the data type
|
|
| 294 | + -- For a type family `cab_lhs` is exactly the family arity
|
|
| 295 | + -- See Note [Eta reduction for data families]
|
|
| 296 | + |
|
| 291 | 297 | , cab_rhs :: Type
|
| 292 | 298 | -- ^ Right-hand side of the equality
|
| 293 | 299 | -- See Note [CoAxioms are homogeneous]
|
| ... | ... | @@ -36,7 +36,7 @@ module GHC.Core.Predicate ( |
| 36 | 36 | |
| 37 | 37 | -- Equality left-hand sides
|
| 38 | 38 | CanEqLHS(..), canEqLHS_maybe, canTyFamEqLHS_maybe,
|
| 39 | - canEqLHSKind, canEqLHSType, eqCanEqLHS
|
|
| 39 | + canEqLHSKind, canEqLHSType, eqCanEqLHS, saturatedFamApp_maybe
|
|
| 40 | 40 | |
| 41 | 41 | ) where
|
| 42 | 42 | |
| ... | ... | @@ -61,6 +61,8 @@ import GHC.Utils.Misc |
| 61 | 61 | import GHC.Utils.Panic
|
| 62 | 62 | import GHC.Data.FastString
|
| 63 | 63 | |
| 64 | +import GHC.Exts( inline )
|
|
| 65 | + |
|
| 64 | 66 | |
| 65 | 67 | {- *********************************************************************
|
| 66 | 68 | * *
|
| ... | ... | @@ -700,7 +702,9 @@ types/kinds are fully settled and zonked. |
| 700 | 702 | -- See also Note [Ordering of implicit variables] in "GHC.Rename.HsType"
|
| 701 | 703 | |
| 702 | 704 | scopedSort :: [Var] -> [Var]
|
| 703 | -scopedSort = go [] []
|
|
| 705 | +scopedSort xs
|
|
| 706 | + | null xs = []
|
|
| 707 | + | otherwise = go [] [] xs
|
|
| 704 | 708 | where
|
| 705 | 709 | go :: [Var] -- already sorted, in reverse order
|
| 706 | 710 | -> [TyCoVarSet] -- each set contains all the variables which must be placed
|
| ... | ... | @@ -781,13 +785,19 @@ canEqLHS_maybe xi |
| 781 | 785 | | otherwise
|
| 782 | 786 | = canTyFamEqLHS_maybe xi
|
| 783 | 787 | |
| 784 | -canTyFamEqLHS_maybe :: Type -> Maybe CanEqLHS
|
|
| 785 | -canTyFamEqLHS_maybe xi
|
|
| 788 | +saturatedFamApp_maybe :: Type -> Maybe (TyCon,[Type])
|
|
| 789 | +saturatedFamApp_maybe xi
|
|
| 786 | 790 | | Just (tc, args) <- tcSplitTyConApp_maybe xi
|
| 787 | 791 | , isTypeFamilyTyCon tc
|
| 788 | 792 | , args `lengthIs` tyConArity tc
|
| 789 | - = Just $ TyFamLHS tc args
|
|
| 793 | + = Just (tc,args)
|
|
| 794 | + | otherwise
|
|
| 795 | + = Nothing
|
|
| 790 | 796 | |
| 797 | +canTyFamEqLHS_maybe :: Type -> Maybe CanEqLHS
|
|
| 798 | +canTyFamEqLHS_maybe xi
|
|
| 799 | + | Just (tc, args) <- inline saturatedFamApp_maybe xi
|
|
| 800 | + = Just $ TyFamLHS tc args
|
|
| 791 | 801 | | otherwise
|
| 792 | 802 | = Nothing
|
| 793 | 803 |
| ... | ... | @@ -1159,10 +1159,12 @@ nice tight loops. |
| 1159 | 1159 | {-# INLINE afvFolder #-} -- See Note [Any-free-var folder]
|
| 1160 | 1160 | afvFolder :: TyCoFolder (FV (BoundVars, TyCoVar -> Bool) DM.Any)
|
| 1161 | 1161 | -- 'afvFolder' is short for "any-free-var folder", good for checking
|
| 1162 | --- if any /deep/ free var of a type satisfies a predicate `check_fv`
|
|
| 1162 | +-- if any /shallow/ free var of a type satisfies a predicate `check_fv`
|
|
| 1163 | 1163 | -- The "env" of the (FV env Any) is a pair (bvs,pred) of
|
| 1164 | 1164 | -- the bound variables (which are definitely not free), and
|
| 1165 | 1165 | -- an "interesting var" predicate which the client supplies
|
| 1166 | +--
|
|
| 1167 | +-- You can get "deep" by supplying a predicate that also looks in the kind
|
|
| 1166 | 1168 | afvFolder = TyCoFolder { tcf_view = noView -- See Note [Free vars and synonyms]
|
| 1167 | 1169 | , tcf_tyvar = do_tcv
|
| 1168 | 1170 | , tcf_covar = do_tcv
|
| ... | ... | @@ -1173,8 +1175,7 @@ afvFolder = TyCoFolder { tcf_view = noView -- See Note [Free vars and synonyms] |
| 1173 | 1175 | -- Check the variable itself with check_fv,
|
| 1174 | 1176 | -- and check its kind (this is a deep folder)
|
| 1175 | 1177 | do_tcv tcv = MkFV $ \ (bvs,check_fv) ->
|
| 1176 | - Any (not (tcv `elemVarSet` bvs) &&
|
|
| 1177 | - (check_fv tcv || runAny check_fv (afv_type (varType tcv))))
|
|
| 1178 | + Any (not (tcv `elemVarSet` bvs) && check_fv tcv)
|
|
| 1178 | 1179 | do_hole hole = do_tcv (coHoleCoVar hole)
|
| 1179 | 1180 | |
| 1180 | 1181 | afv_type :: Type -> FV (BoundVars, TyVar -> Bool) DM.Any
|
| ... | ... | @@ -1186,16 +1187,32 @@ runAny :: (TyVar -> Bool) -> FV (BoundVars, TyCoVar -> Bool) DM.Any -> Bool |
| 1186 | 1187 | {-# INLINE runAny #-}
|
| 1187 | 1188 | runAny check_fv fvs = DM.getAny (runFV fvs (emptyVarSet, check_fv))
|
| 1188 | 1189 | |
| 1190 | +---------------------------------------------
|
|
| 1191 | +-- anyShallowFreeVarsOfType and friends look only for shallow free vars
|
|
| 1192 | +-- (Currently not needed, left here in case we need it one day)
|
|
| 1193 | +-- anyShallowFreeVarsOfType :: (TyCoVar -> Bool) -> Type -> Bool
|
|
| 1194 | +-- {-# INLINE anyShallowFreeVarsOfType #-}
|
|
| 1195 | +-- anyShallowFreeVarsOfType check_fv ty = runAny check_fv (afv_type ty)
|
|
| 1196 | + |
|
| 1197 | +---------------------------------------------
|
|
| 1198 | +-- anyFreeVarsOfType and friends look for deep free vars
|
|
| 1199 | + |
|
| 1200 | +deep_check :: (TyCoVar -> Bool) -> TyCoVar -> Bool
|
|
| 1201 | +-- This is inefficient because if one tyvar occurs many times
|
|
| 1202 | +-- in a type, it'll look in its kind at each occurrence. Boo.
|
|
| 1203 | +deep_check check_fv tcv = check_fv tcv || anyFreeVarsOfType check_fv (varType tcv)
|
|
| 1204 | + |
|
| 1189 | 1205 | anyFreeVarsOfType :: (TyCoVar -> Bool) -> Type -> Bool
|
| 1190 | 1206 | {-# INLINE anyFreeVarsOfType #-}
|
| 1191 | -anyFreeVarsOfType check_fv ty = runAny check_fv (afv_type ty)
|
|
| 1207 | +-- Looks deeply, into the kinds of the free vars
|
|
| 1208 | +anyFreeVarsOfType check_fv ty = runAny (deep_check check_fv) (afv_type ty)
|
|
| 1192 | 1209 | |
| 1193 | 1210 | anyFreeVarsOfTypes :: (TyCoVar -> Bool) -> [Type] -> Bool
|
| 1194 | 1211 | {-# INLINE anyFreeVarsOfTypes #-}
|
| 1195 | -anyFreeVarsOfTypes check_fv tys = runAny check_fv (afv_types tys)
|
|
| 1212 | +anyFreeVarsOfTypes check_fv tys = runAny (deep_check check_fv) (afv_types tys)
|
|
| 1196 | 1213 | |
| 1197 | 1214 | anyFreeVarsOfCo :: (TyCoVar -> Bool) -> Coercion -> Bool
|
| 1198 | -anyFreeVarsOfCo check_fv co = runAny check_fv (afv_co co)
|
|
| 1215 | +anyFreeVarsOfCo check_fv co = runAny (deep_check check_fv) (afv_co co)
|
|
| 1199 | 1216 | |
| 1200 | 1217 | noFreeVarsOfType :: Type -> Bool
|
| 1201 | 1218 | noFreeVarsOfType ty = not $ runAny (const True) (afv_type ty)
|
| ... | ... | @@ -1206,6 +1223,7 @@ noFreeVarsOfTypes tys = not $ runAny (const True) (afv_types tys) |
| 1206 | 1223 | noFreeVarsOfCo :: Coercion -> Bool
|
| 1207 | 1224 | noFreeVarsOfCo co = not $ runAny (const True) (afv_co co)
|
| 1208 | 1225 | |
| 1226 | + |
|
| 1209 | 1227 | {-
|
| 1210 | 1228 | ************************************************************************
|
| 1211 | 1229 | * *
|
| ... | ... | @@ -48,6 +48,8 @@ module GHC.Core.TyCo.Subst |
| 48 | 48 | substTyCoBndr,
|
| 49 | 49 | substVarBndrUsing,
|
| 50 | 50 | checkValidSubst, isValidTCvSubst,
|
| 51 | + |
|
| 52 | + deepSubstTy
|
|
| 51 | 53 | ) where
|
| 52 | 54 | |
| 53 | 55 | import GHC.Prelude
|
| ... | ... | @@ -775,9 +777,15 @@ substThetaUnchecked = substTysUnchecked |
| 775 | 777 | -- building no thunks. See Note [Specialising mappers] in GHC.Core.TyCo.Make
|
| 776 | 778 | type SubstM = StrictReaderT Subst StrictIdentity
|
| 777 | 779 | |
| 778 | -runSubstM :: SubstM a -> Subst -> a
|
|
| 779 | -runSubstM m subst = runStrictIdentity (runStrictReaderT m subst)
|
|
| 780 | +runSubstM :: forall a. (a -> SubstM a) -> Subst -> a -> a
|
|
| 780 | 781 | {-# INLINE runSubstM #-}
|
| 782 | +runSubstM tx subst x = runStrictIdentity (runStrictReaderT (tx x) subst)
|
|
| 783 | + |
|
| 784 | +subst_ty :: Subst -> Type -> Type
|
|
| 785 | +subst_co :: Subst -> Coercion -> Coercion
|
|
| 786 | +(subst_ty, subst_co)
|
|
| 787 | + = case mapTyCo substTyCoMapper of
|
|
| 788 | + (ms_ty, _, ms_co, _) -> (runSubstM ms_ty, runSubstM ms_co)
|
|
| 781 | 789 | |
| 782 | 790 | substTyCoMapper :: TyCoMapper SubstM
|
| 783 | 791 | substTyCoMapper
|
| ... | ... | @@ -785,8 +793,8 @@ substTyCoMapper |
| 785 | 793 | , tcm_covar = subst_cv
|
| 786 | 794 | , tcm_hole = subst_ch
|
| 787 | 795 | , tcm_tycobinder = tcv_bndr
|
| 788 | - , tcm_tcapp_ty = tcapp_ty
|
|
| 789 | - , tcm_tcapp_co = tcapp_co
|
|
| 796 | + , tcm_tcapp_ty = nopTcAppTy
|
|
| 797 | + , tcm_tcapp_co = nopTcAppCo
|
|
| 790 | 798 | }
|
| 791 | 799 | where
|
| 792 | 800 | subst_tv tv = StrictReaderT $ \subst -> return (substTyVar subst tv)
|
| ... | ... | @@ -802,23 +810,15 @@ substTyCoMapper |
| 802 | 810 | |
| 803 | 811 | -- Avoid allocation in this very
|
| 804 | 812 | -- common case (E.g. Int, LiftedRep etc)
|
| 805 | - tcapp_ty :: Type -> TyCon -> [Type] -> SubstM Type
|
|
| 806 | - tcapp_ty ty tc tys'
|
|
| 807 | - | null tys' = return ty
|
|
| 808 | - | otherwise = return (mkTyConApp tc tys')
|
|
| 809 | - tcapp_co :: Coercion -> Role -> TyCon -> [Coercion] -> SubstM Coercion
|
|
| 810 | - tcapp_co co r tc cos'
|
|
| 811 | - | null cos' = return co
|
|
| 812 | - | otherwise = return (mkTyConAppCo r tc cos')
|
|
| 813 | +nopTcAppTy :: Type -> TyCon -> [Type] -> SubstM Type
|
|
| 814 | +nopTcAppTy ty tc tys'
|
|
| 815 | + | null tys' = return ty
|
|
| 816 | + | otherwise = return (mkTyConApp tc tys')
|
|
| 813 | 817 | |
| 814 | -subst_ty :: Subst -> Type -> Type
|
|
| 815 | -subst_co :: Subst -> Coercion -> Coercion
|
|
| 816 | -(subst_ty, subst_co)
|
|
| 817 | - = case mapTyCo substTyCoMapper of
|
|
| 818 | - (ms_ty, _, ms_co, _) -> (run ms_ty, run ms_co)
|
|
| 819 | - where
|
|
| 820 | - run :: forall a. (a -> SubstM a) -> Subst -> a -> a
|
|
| 821 | - run ms subst x = runSubstM (ms x) subst
|
|
| 818 | +nopTcAppCo :: Coercion -> Role -> TyCon -> [Coercion] -> SubstM Coercion
|
|
| 819 | +nopTcAppCo co r tc cos'
|
|
| 820 | + | null cos' = return co
|
|
| 821 | + | otherwise = return (mkTyConAppCo r tc cos')
|
|
| 822 | 822 | |
| 823 | 823 | substTyVar :: Subst -> TyVar -> Type
|
| 824 | 824 | substTyVar (Subst _ _ tenv _) tv
|
| ... | ... | @@ -1019,3 +1019,86 @@ it is /very/ valuable to /keep/ it empty: |
| 1019 | 1019 | If the substitution is empty, this is a no-op -- but only if it
|
| 1020 | 1020 | is empty!
|
| 1021 | 1021 | -}
|
| 1022 | + |
|
| 1023 | + |
|
| 1024 | +{- **********************************************************************
|
|
| 1025 | +%* *
|
|
| 1026 | + Deep substitution
|
|
| 1027 | +%* *
|
|
| 1028 | +%********************************************************************* -}
|
|
| 1029 | + |
|
| 1030 | +{- Note [Deep substitution]
|
|
| 1031 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1032 | +Deep substitution applies the substitution to the /kinds/ of un-substituted
|
|
| 1033 | +type variables. Suppose the substitution is
|
|
| 1034 | + [ k :-> Type ]
|
|
| 1035 | +and we apply it to the type
|
|
| 1036 | + Proxy k (a :: k)
|
|
| 1037 | +Ordinary shallow substitution will give
|
|
| 1038 | + Proxy Type (a :: k)
|
|
| 1039 | +which is ill-kinded. Deep substitution will give
|
|
| 1040 | + Proxy Type (a :: Type)
|
|
| 1041 | + |
|
| 1042 | +Ordinary (shallow) substitution is usually fine, because we will substitute for
|
|
| 1043 | +`a` as well, but not always. In particular, the pure unifier in GHC.Core.Unify
|
|
| 1044 | +uses `niFixSubst` to find a fixpoint, and we really don't want domain tyvars
|
|
| 1045 | +appearing in the range. See Note [Finding the substitution fixpoint].
|
|
| 1046 | + |
|
| 1047 | +Wrinkles:
|
|
| 1048 | + |
|
| 1049 | +(DS1) Deep substitution risks being rather inefficient because it re-applies the
|
|
| 1050 | + substitution to the kind at /each occurrence/ of a free variable. We could
|
|
| 1051 | + perhaps find the free vars, and build a re-kinding substitution, but that's a
|
|
| 1052 | + bit more complicated.
|
|
| 1053 | + |
|
| 1054 | +(DS2) Deep substitution, as implemented here, relies on invariant
|
|
| 1055 | + (NoTypeShadowing); see Note [No type-shadowing in Core] in Core.hs.
|
|
| 1056 | + Otherwise we may have e.g.
|
|
| 1057 | + S = [r :-> LiftedRep] in-scope = {r, x}
|
|
| 1058 | + T = forall (r :: RuntimeRep). (x :: TYPE r) -> ...
|
|
| 1059 | + and we would want to apply the outer substitution S to the
|
|
| 1060 | + occurrence of r in the kind of x. But we'll have removed it
|
|
| 1061 | + from the subsitution when pasing the 'forall r'.
|
|
| 1062 | +-}
|
|
| 1063 | + |
|
| 1064 | +deepSubstTyCoMapper :: TyCoMapper SubstM
|
|
| 1065 | +deepSubstTyCoMapper
|
|
| 1066 | + = TyCoMapper { tcm_tyvar = subst_tv
|
|
| 1067 | + , tcm_covar = subst_cv
|
|
| 1068 | + , tcm_hole = subst_ch
|
|
| 1069 | + , tcm_tycobinder = tcv_bndr
|
|
| 1070 | + , tcm_tcapp_ty = nopTcAppTy
|
|
| 1071 | + , tcm_tcapp_co = nopTcAppCo
|
|
| 1072 | + }
|
|
| 1073 | + where
|
|
| 1074 | + subst_tv tv = StrictReaderT $ \subst -> return (deepSubstTyVar subst tv)
|
|
| 1075 | + subst_cv cv = StrictReaderT $ \subst -> return (deepSubstCoVar subst cv)
|
|
| 1076 | + subst_ch ch = StrictReaderT $ \subst -> return (deepSubstCoHole subst ch)
|
|
| 1077 | + |
|
| 1078 | + tcv_bndr :: TyCoVar -> ForAllTyFlag -> (TyCoVar -> SubstM r) -> SubstM r
|
|
| 1079 | + tcv_bndr tcv _vis k
|
|
| 1080 | + = StrictReaderT $ \subst ->
|
|
| 1081 | + let !(subst', tcv') = substVarBndrUsing deepSubstTy subst tcv
|
|
| 1082 | + in runStrictReaderT (k tcv') subst'
|
|
| 1083 | + |
|
| 1084 | +deepSubstTy :: Subst -> Type -> Type
|
|
| 1085 | +deepSubstTy = case mapTyCo deepSubstTyCoMapper of
|
|
| 1086 | + (subst_ty, _, _, _) -> runSubstM subst_ty
|
|
| 1087 | + |
|
| 1088 | +deepSubstTyVar :: Subst -> TyVar -> Type
|
|
| 1089 | +deepSubstTyVar subst@(Subst _ _ tenv _) tv
|
|
| 1090 | + = assert (isTyVar tv) $
|
|
| 1091 | + case lookupVarEnv tenv tv of
|
|
| 1092 | + Just ty -> ty
|
|
| 1093 | + Nothing -> TyVarTy (updateVarType (deepSubstTy subst) tv)
|
|
| 1094 | + |
|
| 1095 | +deepSubstCoVar :: Subst -> CoVar -> Coercion
|
|
| 1096 | +deepSubstCoVar subst@(Subst _ _ _ cenv) cv
|
|
| 1097 | + = case lookupVarEnv cenv cv of
|
|
| 1098 | + Just co -> co
|
|
| 1099 | + Nothing -> CoVarCo (updateVarType (deepSubstTy subst) cv)
|
|
| 1100 | + |
|
| 1101 | +deepSubstCoHole :: Subst -> CoercionHole -> Coercion
|
|
| 1102 | +-- See Note [Substituting in a coercion hole]
|
|
| 1103 | +deepSubstCoHole subst h@(CH { ch_co_var = cv })
|
|
| 1104 | + = HoleCo (h { ch_co_var = updateVarType (deepSubstTy subst) cv }) |
| ... | ... | @@ -483,7 +483,7 @@ expandTypeSynonyms ty |
| 483 | 483 | expandTypeSynonymsX :: Subst -> Type -> Type
|
| 484 | 484 | expandTypeSynonymsX
|
| 485 | 485 | = case mapTyCo expandTypeSynonymMapper of
|
| 486 | - (exp_ty, _, _, _) -> \subst ty -> runSubstM (exp_ty ty) subst
|
|
| 486 | + (exp_ty, _, _, _) -> runSubstM exp_ty
|
|
| 487 | 487 | |
| 488 | 488 | expandTypeSynonymMapper :: TyCoMapper SubstM
|
| 489 | 489 | -- Just like substitution, but treat TyConApp specially
|
| ... | ... | @@ -28,13 +28,12 @@ import GHC.Types.Var.Env |
| 28 | 28 | import GHC.Types.Var.Set
|
| 29 | 29 | import GHC.Core.Type hiding ( getTvSubstEnv )
|
| 30 | 30 | import GHC.Core.Coercion hiding ( getCvSubstEnv )
|
| 31 | -import GHC.Core.Predicate( scopedSort )
|
|
| 32 | 31 | import GHC.Core.TyCon
|
| 33 | 32 | import GHC.Core.Predicate( CanEqLHS(..), canEqLHS_maybe )
|
| 34 | 33 | import GHC.Core.TyCon.Env
|
| 35 | 34 | import GHC.Core.TyCo.Rep
|
| 36 | 35 | import GHC.Core.TyCo.Compare ( eqType, tcEqType, tcEqTyConAppArgs )
|
| 37 | -import GHC.Core.TyCo.Subst ( mkTvSubst )
|
|
| 36 | +import GHC.Core.TyCo.Subst ( mkTvSubst, deepSubstTy )
|
|
| 38 | 37 | import GHC.Core.Map.Type
|
| 39 | 38 | import GHC.Core.Multiplicity
|
| 40 | 39 | |
| ... | ... | @@ -1063,21 +1062,31 @@ During unification we use a TvSubstEnv/CvSubstEnv pair that is |
| 1063 | 1062 | |
| 1064 | 1063 | Note [Finding the substitution fixpoint]
|
| 1065 | 1064 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 1066 | -Finding the fixpoint of a non-idempotent substitution arising from a
|
|
| 1067 | -unification is much trickier than it looks, because of kinds. Consider
|
|
| 1065 | +We want an /idempotent/ substitution, so `niFixSubst` takes a non-idempotent
|
|
| 1066 | +one and composes it with itself until it becomes idempotent. Thus if the original
|
|
| 1067 | +is S0, we compute S1 = S0 o S0, S2 = S1 o S1, etc.
|
|
| 1068 | + |
|
| 1069 | +A variable chain v0 :-> v1 :-> ... :-> vm therefore takes about log2(m) rounds,
|
|
| 1070 | +The unifier can build such chains. For example:
|
|
| 1071 | + (a, a, a, ..., a) ~ (x1, x2, x3, ..., xm)
|
|
| 1072 | +produces a :-> x1, x1 :-> x2, ..., x(m-1) :-> xm.
|
|
| 1073 | + |
|
| 1074 | +Finding the fixpoint is much trickier than it looks, because of kinds.
|
|
| 1075 | +Consider
|
|
| 1068 | 1076 | T k (H k (f:k)) ~ T * (g:*)
|
| 1069 | 1077 | If we unify, we get the substitution
|
| 1070 | 1078 | [ k -> *
|
| 1071 | 1079 | , g -> H k (f:k) ]
|
| 1080 | +This isn't idempotent: it mentions `k` in the range.
|
|
| 1081 | + |
|
| 1072 | 1082 | To make it idempotent we don't want to get just
|
| 1073 | 1083 | [ k -> *
|
| 1074 | 1084 | , g -> H * (f:k) ]
|
| 1075 | -We also want to substitute inside f's kind, to get
|
|
| 1076 | - [ k -> *
|
|
| 1077 | - , g -> H k (f:*) ]
|
|
| 1078 | -If we don't do this, we may apply the substitution to something,
|
|
| 1079 | -and get an ill-formed type, i.e. one where typeKind will fail.
|
|
| 1085 | +because (H * (f:k)) is itself ill-kinded, and `typeKind` will fail.
|
|
| 1080 | 1086 | This happened, for example, in #9106.
|
| 1087 | +So (yuckily) we must also substitute inside f's kind, to get
|
|
| 1088 | + [ k -> *
|
|
| 1089 | + , g -> H * (f:*) ]
|
|
| 1081 | 1090 | |
| 1082 | 1091 | It gets worse. In #14164 we wanted to take the fixpoint of
|
| 1083 | 1092 | this substitution
|
| ... | ... | @@ -1090,84 +1099,53 @@ the invocation of F! We don't have a function that recursively |
| 1090 | 1099 | applies substitutions inside the kinds of variable occurrences (and
|
| 1091 | 1100 | probably rightly so).
|
| 1092 | 1101 | |
| 1093 | -So, we work as follows:
|
|
| 1094 | - |
|
| 1095 | - 1. Start with the current substitution (which we are
|
|
| 1096 | - trying to fixpoint
|
|
| 1097 | - [ xs :-> F a (z :: a) (rest :: G a (z :: a))
|
|
| 1098 | - , a :-> b ]
|
|
| 1099 | - |
|
| 1100 | - 2. Take all the free vars of the range of the substitution:
|
|
| 1101 | - {a, z, rest, b}
|
|
| 1102 | - NB: the free variable finder closes over
|
|
| 1103 | - the kinds of variable occurrences
|
|
| 1104 | - |
|
| 1105 | - 3. If none are in the domain of the substitution, stop.
|
|
| 1106 | - We have found a fixpoint.
|
|
| 1107 | - |
|
| 1108 | - 4. Remove the variables that are bound by the substitution, leaving
|
|
| 1109 | - {z, rest, b}
|
|
| 1110 | - |
|
| 1111 | - 5. Do a topo-sort to put them in dependency order:
|
|
| 1112 | - [ b :: *, z :: a, rest :: G a z ]
|
|
| 1113 | - |
|
| 1114 | - 6. Apply the substitution left-to-right to the kinds of these
|
|
| 1115 | - tyvars, extending it each time with a new binding, so we
|
|
| 1116 | - finish up with
|
|
| 1117 | - [ xs :-> ..as before..
|
|
| 1118 | - , a :-> b
|
|
| 1119 | - , b :-> b :: *
|
|
| 1120 | - , z :-> z :: b
|
|
| 1121 | - , rest :-> rest :: G b (z :: b) ]
|
|
| 1122 | - Note that rest now has the right kind
|
|
| 1123 | - |
|
| 1124 | - 7. Apply this extended substitution (once) to the range of the
|
|
| 1125 | - /original/ substitution. (Note that the extended substitution
|
|
| 1126 | - would go on forever if you tried to find its fixpoint, because it
|
|
| 1127 | - maps z to z.)
|
|
| 1128 | - |
|
| 1129 | - 8. And go back to step 1
|
|
| 1130 | - |
|
| 1131 | -In Step 6 we use the free vars from Step 2 as the initial
|
|
| 1132 | -in-scope set, because all of those variables appear in the
|
|
| 1133 | -range of the substitution, so they must all be in the in-scope
|
|
| 1134 | -set. But NB that the type substitution engine does not look up
|
|
| 1135 | -variables in the in-scope set; it is used only to ensure no
|
|
| 1136 | -shadowing.
|
|
| 1102 | +Ugh! This whole thing is pretty horrible. But the solution is simple enough:
|
|
| 1103 | + |
|
| 1104 | + Use deep substitution (deepSubstTy)
|
|
| 1105 | + |
|
| 1106 | +(deepSubst `s` (Proxy k (a::k)) applies the substitution `s` not only to
|
|
| 1107 | +the occurrence of `k` in the argument of `Proxy`, but also to the `k` inside
|
|
| 1108 | +the kind of `a`. See Note [Deep substitution] in GHC.Core.TyCo.Subst.
|
|
| 1109 | + |
|
| 1110 | +So `niFixSubst` just applies the substitution /deeply/ to the types in its
|
|
| 1111 | +range, until we reach a fixed point. Easy!
|
|
| 1112 | + |
|
| 1113 | +Historical Note:
|
|
| 1114 | + Immediately prior to this solution there was a previous, more complicated
|
|
| 1115 | + `niFixSubst` which involved finding the (deep) free variables and "re-kinding"
|
|
| 1116 | + them. It accomplished essentially the same things, and it avoided the
|
|
| 1117 | + potential duplication noted in Note [Deep substitution]. But it was pretty
|
|
| 1118 | + subtle and this version is more obviously correct.
|
|
| 1119 | +End of Historical Note
|
|
| 1137 | 1120 | -}
|
| 1138 | 1121 | |
| 1139 | 1122 | niFixSubst :: InScopeSet -> TvSubstEnv -> Subst
|
| 1140 | 1123 | -- Find the idempotent fixed point of the non-idempotent substitution
|
| 1141 | 1124 | -- This is surprisingly tricky:
|
| 1142 | 1125 | -- see Note [Finding the substitution fixpoint]
|
| 1143 | --- ToDo: use laziness instead of iteration?
|
|
| 1144 | 1126 | niFixSubst in_scope tenv
|
| 1145 | - | not_fixpoint = niFixSubst in_scope (mapVarEnv (substTy subst) tenv)
|
|
| 1146 | - | otherwise = tenv_subst
|
|
| 1127 | + | isEmptyVarEnv tenv -- Fast path for common case
|
|
| 1128 | + = mkEmptySubst in_scope
|
|
| 1129 | + | otherwise
|
|
| 1130 | + = -- pprTrace "niFixSubst" (vcat [ text "In: " <+> ppr tenv
|
|
| 1131 | + -- , text "Out:" <+> ppr (S.getTvSubstEnv subst) ])
|
|
| 1132 | + subst
|
|
| 1147 | 1133 | where
|
| 1148 | - tenv_subst = mkTvSubst in_scope tenv -- This is our starting point
|
|
| 1149 | - |
|
| 1150 | - range_tvs :: [TyVar]
|
|
| 1151 | - range_tvs = nonDetVarSetElems $
|
|
| 1152 | - tyCoVarsOfTypes $
|
|
| 1153 | - nonDetEltsUFM tenv
|
|
| 1154 | - -- It's OK to use nonDetEltsUFM (twice) here because
|
|
| 1155 | - -- the order of range_tvs is immaterial
|
|
| 1156 | - |
|
| 1157 | - not_fixpoint = any in_domain range_tvs
|
|
| 1158 | - in_domain tv = tv `elemVarEnv` tenv
|
|
| 1134 | + subst = niFixSubst' 1 in_scope tenv
|
|
| 1159 | 1135 | |
| 1160 | - free_tvs = scopedSort (filterOut in_domain range_tvs)
|
|
| 1161 | - |
|
| 1162 | - -- See Note [Finding the substitution fixpoint], Step 6
|
|
| 1163 | - subst = foldl' add_free_tv tenv_subst free_tvs
|
|
| 1164 | - |
|
| 1165 | - add_free_tv :: Subst -> TyVar -> Subst
|
|
| 1166 | - add_free_tv subst tv
|
|
| 1167 | - | isTyVar tv = extendTvSubst subst tv (mkTyVarTy tv')
|
|
| 1168 | - | otherwise = subst -- Ignore free coercion variables
|
|
| 1169 | - where
|
|
| 1170 | - tv' = updateTyVarKind (substTy subst) tv
|
|
| 1136 | +niFixSubst' :: Int -> InScopeSet -> TvSubstEnv -> Subst
|
|
| 1137 | +niFixSubst' n in_scope tenv_orig
|
|
| 1138 | + | fixpoint_found = mkTvSubst in_scope tenv_orig
|
|
| 1139 | + | otherwise = niFixSubst' (n+1) in_scope tenv_new
|
|
| 1140 | + where
|
|
| 1141 | + in_dom tv = tv `elemVarEnv` tenv_orig
|
|
| 1142 | + tenv_new = mapVarEnv (deepSubstTy subst) tenv_orig
|
|
| 1143 | + subst = mkTvSubst in_scope tenv_orig
|
|
| 1144 | + |
|
| 1145 | + fixpoint_found = nonDetStrictFoldUFM and_fix True tenv_orig
|
|
| 1146 | + and_fix :: Type -> Bool -> Bool
|
|
| 1147 | + and_fix _ False = False
|
|
| 1148 | + and_fix ty _ = not (anyFreeVarsOfType in_dom ty)
|
|
| 1171 | 1149 | |
| 1172 | 1150 | {-
|
| 1173 | 1151 | ************************************************************************
|
| ... | ... | @@ -16,6 +16,7 @@ import GHC.Prelude |
| 16 | 16 | import GHC.Driver.DynFlags
|
| 17 | 17 | import GHC.Driver.Env
|
| 18 | 18 | |
| 19 | +import GHC.Core.Predicate( saturatedFamApp_maybe )
|
|
| 19 | 20 | import GHC.Core.FamInstEnv
|
| 20 | 21 | import GHC.Core.Coercion
|
| 21 | 22 | import GHC.Core.TyCon
|
| ... | ... | @@ -715,15 +716,9 @@ reportInjectivityErrors dflags fi_ax axiom inj |
| 715 | 716 | when wrong_bare_rhs $ reportBareVariableInRHSErr fam_tc bare_variables axiom
|
| 716 | 717 | |
| 717 | 718 | -- | Is type headed by a type family application?
|
| 718 | -isTFHeaded :: Type -> Bool
|
|
| 719 | 719 | -- See Note [Verifying injectivity annotation], case 3.
|
| 720 | -isTFHeaded ty | Just ty' <- coreView ty
|
|
| 721 | - = isTFHeaded ty'
|
|
| 722 | -isTFHeaded ty | (TyConApp tc args) <- ty
|
|
| 723 | - , isTypeFamilyTyCon tc
|
|
| 724 | - = args `lengthIs` tyConArity tc
|
|
| 725 | -isTFHeaded _ = False
|
|
| 726 | - |
|
| 720 | +isTFHeaded :: Type -> Bool
|
|
| 721 | +isTFHeaded ty = isJust (saturatedFamApp_maybe ty)
|
|
| 727 | 722 | |
| 728 | 723 | -- | If a RHS is a bare type variable return a set of LHS patterns that are not
|
| 729 | 724 | -- bare type variables.
|
| ... | ... | @@ -24,16 +24,16 @@ import GHC.Tc.Types.Constraint |
| 24 | 24 | import GHC.Core.FamInstEnv
|
| 25 | 25 | import GHC.Core.Coercion
|
| 26 | 26 | import GHC.Core.TyCo.Rep( Type(..) )
|
| 27 | -import GHC.Core.Predicate( EqRel(..) )
|
|
| 27 | +import GHC.Core.TyCo.Subst( deepSubstTy, elemSubst, extendTvSubstWithClone )
|
|
| 28 | +import GHC.Core.Predicate( EqRel(..), saturatedFamApp_maybe )
|
|
| 28 | 29 | import GHC.Core.TyCon
|
| 29 | 30 | import GHC.Core.Unify( AmIUnifying(..)
|
| 30 | 31 | , tcUnifyTysForInjectivity, typeListsAreApart )
|
| 31 | 32 | import GHC.Core.Coercion.Axiom
|
| 32 | -import GHC.Core.TyCo.Subst( elemSubst, extendTvSubstWithClone )
|
|
| 33 | 33 | |
| 34 | 34 | import GHC.Builtin.WiredIn.TypeLits( tryInteractTopFam, tryInteractInertFam )
|
| 35 | 35 | |
| 36 | -import GHC.Types.Var( TyVar, tyVarKind, setTyVarKind )
|
|
| 36 | +import GHC.Types.Var( TyVar, updateVarType, tyVarKind )
|
|
| 37 | 37 | import GHC.Types.Var.Set
|
| 38 | 38 | import GHC.Types.Var.Env( mkInScopeSet )
|
| 39 | 39 | |
| ... | ... | @@ -57,7 +57,6 @@ Here is our plan for dealing with functional dependencies |
| 57 | 57 | * send the current constraint back to the start of the pipeline;
|
| 58 | 58 | it might now be soluble, and it probably isn't inert
|
| 59 | 59 | |
| 60 | - |
|
| 61 | 60 | * Once a unification is done, it can't be un-done. So we must be very careful
|
| 62 | 61 | not to threaten completeness by doing a unification when there might be
|
| 63 | 62 | another way to solve the constraint.
|
| ... | ... | @@ -613,6 +612,7 @@ tryFamEqFunDeps mode eqs_for_me fam_tc work_args |
| 613 | 612 | |
| 614 | 613 | mkTopFamEqFDs :: TyCon -> [TcType] -> EqCt -> SolverStage [FunDepEqns]
|
| 615 | 614 | mkTopFamEqFDs fam_tc work_args work_item
|
| 615 | + -- NB: work_args exactly saturate fam_tc
|
|
| 616 | 616 | | isOpenTypeFamilyTyCon fam_tc
|
| 617 | 617 | , Injective inj_flags <- tyConInjectivityInfo fam_tc
|
| 618 | 618 | = -- Open, injective type families
|
| ... | ... | @@ -694,6 +694,8 @@ hasRelevantGiven eqs_for_me work_args (EqCt { eq_rhs = work_rhs }) |
| 694 | 694 | getRelevantBranches :: CoAxiom Branched -> [TcType] -> Xi -> [FunDepEqns]
|
| 695 | 695 | -- Return the FunDepEqns that arise from each relevant branch
|
| 696 | 696 | -- Implements Note [Relevance]
|
| 697 | +-- Caller will only use these FunDepEqns if there is just one relevant
|
|
| 698 | +-- equation, i.e. the returned [FunDepEqns] is a singleton.
|
|
| 697 | 699 | getRelevantBranches ax work_args work_rhs
|
| 698 | 700 | = go (fromBranches (coAxiomBranches ax))
|
| 699 | 701 | where
|
| ... | ... | @@ -709,24 +711,33 @@ getRelevantBranches ax work_args work_rhs |
| 709 | 711 | , cab_lhs = lhs_tys
|
| 710 | 712 | , cab_rhs = rhs_ty })
|
| 711 | 713 | | Just subst <- tcUnifyTysForInjectivity Unifying (rhs_ty:lhs_tys) work_tys
|
| 712 | - -- See (RW1)-(RW3) in Note [Relevance]
|
|
| 713 | - -- This is a pre-/unification/ check (not matching)
|
|
| 714 | - -- so `subst` can bind both `qtvs` and fvs(work_tys)
|
|
| 715 | - , let (subst',qtvs') = trim_qtvs subst qtvs
|
|
| 716 | - lhs_tys' = substTys subst' lhs_tys
|
|
| 717 | - rhs_ty' = substTy subst' rhs_ty
|
|
| 718 | - branch_tys' = rhs_ty' : lhs_tys'
|
|
| 714 | + -- See (RW1)-(RW3) in Note [Relevance]
|
|
| 715 | + , let lhs_tys' = map (deepSubstTy subst) lhs_tys
|
|
| 716 | + -- deepSubstTy: see (CF8) in Note [Exploiting closed type families]
|
|
| 719 | 717 | , noEarlierMatchCheck lhs_tys' branch -- See (RW4) in Note [Relevance]
|
| 720 | - = Just (FDEqns { fd_qtvs = qtvs'
|
|
| 721 | - , fd_eqs = zipWith Pair branch_tys' work_tys })
|
|
| 722 | - -- Do not apply the substition to `work_tys`;
|
|
| 723 | - -- See (CF7) in Note [Exploiting closed type families]
|
|
| 718 | + = -- Ignore the substitution, except for `noEarlierMatchCheck`
|
|
| 719 | + Just $
|
|
| 720 | + if all (`elemSubst` subst) qtvs
|
|
| 721 | + then -- `subst` eliminates all qtvs; and no qtvs in range of subst
|
|
| 722 | + -- See (CF7)(A) in Note [Exploiting closed type families]
|
|
| 723 | + FDEqns { fd_qtvs = []
|
|
| 724 | + , fd_eqs = zipWith Pair (substTy subst rhs_ty : lhs_tys')
|
|
| 725 | + work_tys }
|
|
| 726 | + -- Do not apply `subst` to `work_tys`;
|
|
| 727 | + -- See (CF9) in Note [Exploiting closed type families]
|
|
| 728 | + |
|
| 729 | + else -- Abandon `subst`; re-create it from (rhs_ty ~ work_rhs)
|
|
| 730 | + -- See (CF7)(B) in Note [Exploiting closed type families]
|
|
| 731 | + FDEqns { fd_qtvs = qtvs
|
|
| 732 | + , fd_eqs = zipWith Pair (rhs_ty:lhs_tys) work_tys }
|
|
| 733 | + |
|
| 724 | 734 | | otherwise
|
| 725 | 735 | = Nothing
|
| 726 | 736 | |
| 727 | 737 | mkTopOpenFamEqFDs :: TyCon -> [Bool] -> [TcType] -> EqCt -> TcS [FunDepEqns]
|
| 728 | 738 | -- Implements (INJFAM:Wanted/top-open)
|
| 729 | 739 | -- See Note [Exploiting open type families]
|
| 740 | +-- NB: work_args exactly saturate fam_tc
|
|
| 730 | 741 | mkTopOpenFamEqFDs fam_tc inj_flags work_args (EqCt { eq_rhs = work_rhs })
|
| 731 | 742 | = do { fam_envs <- getFamInstEnvs
|
| 732 | 743 | ; let branches :: [CoAxBranch]
|
| ... | ... | @@ -739,11 +750,14 @@ mkTopOpenFamEqFDs fam_tc inj_flags work_args (EqCt { eq_rhs = work_rhs }) |
| 739 | 750 | , cab_lhs = branch_lhs_tys
|
| 740 | 751 | , cab_rhs = branch_rhs })
|
| 741 | 752 | | Just subst <- tcUnifyTysForInjectivity Matching [branch_rhs] [work_rhs]
|
| 742 | - , let (subst', qtvs') = trim_qtvs subst branch_qtvs
|
|
| 753 | + -- No need for an apartness check here;
|
|
| 754 | + -- for open type families there are no "preceding" equations
|
|
| 755 | + -- Both branch_lhs_tys and work_args exactly saturate fam_tc
|
|
| 756 | + , let (subst', qtvs') = trimQtvs subst branch_qtvs
|
|
| 743 | 757 | branch_lhs_tys' = substTys subst' branch_lhs_tys
|
| 744 | - -- No need for an apartness check here; for open type families
|
|
| 745 | - -- there are no "preceding" equations
|
|
| 746 | - = Just (mkInjectivityFDEqn inj_flags qtvs' branch_lhs_tys' work_args)
|
|
| 758 | + -- We must apply the substitution here see
|
|
| 759 | + -- the Basic Plan in Note [Exploiting open type families]
|
|
| 760 | + = Just (mkInjectivityFDEqn qtvs' inj_flags branch_lhs_tys' work_args)
|
|
| 747 | 761 | |
| 748 | 762 | | otherwise
|
| 749 | 763 | = Nothing
|
| ... | ... | @@ -756,9 +770,9 @@ mkLocalFamEqFDs eqs_for_me fam_tc inj_flags work_args work_rhs |
| 756 | 770 | = do { let -- eqns_from_inerts: see (INJFAM:Wanted/other)
|
| 757 | 771 | eqns_from_inerts = mapMaybe do_one eqs_for_me
|
| 758 | 772 | -- eqns_from_self: see (INJFAM:Wanted/Self)
|
| 759 | - eqns_from_self = case tcSplitTyConApp_maybe work_rhs of
|
|
| 760 | - Just (tc,rhs_tys) | tc==fam_tc -> [mk_eqn rhs_tys]
|
|
| 761 | - _ -> []
|
|
| 773 | + eqns_from_self = case saturatedFamApp_maybe work_rhs of
|
|
| 774 | + Just (tc, rhs_tys) | fam_tc == tc -> [mk_eqn rhs_tys]
|
|
| 775 | + _ -> []
|
|
| 762 | 776 | |
| 763 | 777 | ; return (eqns_from_inerts ++ eqns_from_self) }
|
| 764 | 778 | where
|
| ... | ... | @@ -768,11 +782,12 @@ mkLocalFamEqFDs eqs_for_me fam_tc inj_flags work_args work_rhs |
| 768 | 782 | | otherwise = Nothing
|
| 769 | 783 | do_one _ = pprPanic "interactFunEq 2" (ppr fam_tc) -- TyVarLHS
|
| 770 | 784 | |
| 771 | - mk_eqn iargs = mkInjectivityFDEqn inj_flags [] work_args iargs
|
|
| 785 | + mk_eqn iargs = mkInjectivityFDEqn [] inj_flags work_args iargs
|
|
| 786 | + |
|
| 772 | 787 | |
| 773 | -trim_qtvs :: Subst -> [TyVar] -> (Subst, [TyVar])
|
|
| 774 | --- Tricky stuff: see (OF1) in Note [Exploiting open type families]
|
|
| 775 | -trim_qtvs unif_subst qtvs
|
|
| 788 | +trimQtvs :: Subst -> [TyVar] -> (Subst, [TyVar])
|
|
| 789 | +-- Tricky stuff: see Note [Exploiting open type families] and Note [trimQtvs]
|
|
| 790 | +trimQtvs unif_subst qtvs
|
|
| 776 | 791 | = go unif_subst qtvs
|
| 777 | 792 | where
|
| 778 | 793 | go :: Subst -> [TyVar] -> (Subst, [TyVar])
|
| ... | ... | @@ -786,10 +801,9 @@ trim_qtvs unif_subst qtvs |
| 786 | 801 | go_fresh subst tv tvs = (subst'', tv':tvs')
|
| 787 | 802 | where
|
| 788 | 803 | !(subst'', tvs') = go subst' tvs
|
| 789 | - tv' = tv `setTyVarKind` substTy subst (tyVarKind tv)
|
|
| 804 | + tv' = updateVarType (substTy subst) tv
|
|
| 790 | 805 | subst' = extendTvSubstWithClone subst tv tv'
|
| 791 | - -- extendTvSubstWithClone: see (OF1b) in
|
|
| 792 | - -- Note [Exploiting open type families]
|
|
| 806 | + -- extendTvSubstWithClone: see (TQ1) in Note [trimQtvs]
|
|
| 793 | 807 | |
| 794 | 808 | |
| 795 | 809 | -----------------------------------------
|
| ... | ... | @@ -883,15 +897,22 @@ mkLocalBuiltinFamEqFDs eqs_for_me fam_tc ops work_args work_rhs |
| 883 | 897 | ; return (eqns_from_inerts ++ eqns_from_self) }
|
| 884 | 898 | |
| 885 | 899 | --------------------
|
| 886 | -mkInjectivityFDEqn :: [Bool] -- Injectivity flags
|
|
| 887 | - -> [TcTyVar] -- Quantify these
|
|
| 900 | +mkInjectivityFDEqn :: [TcTyVar] -- Quantify these
|
|
| 901 | + -> [Bool] -- Injectivity flags
|
|
| 888 | 902 | -> [TcType] -> [TcType] -- Make these equal
|
| 889 | 903 | -> FunDepEqns
|
| 890 | 904 | -- When F s1 s2 s3 ~ F t1 t2 t3, and F has injectivity info [True,False,True]
|
| 891 | 905 | -- return the FDEqns { fd_eqs = [Pair s1 t1, Pair s3 t3] }
|
| 892 | --- The injectivity flags [Bool] will not all be False, but nothing goes wrong if they are
|
|
| 893 | -mkInjectivityFDEqn inj_args qtvs lhs_args rhs_args
|
|
| 894 | - = FDEqns { fd_qtvs = qtvs, fd_eqs = eqs }
|
|
| 906 | +-- The injectivity flags [Bool] will not all be False,
|
|
| 907 | +-- but nothing goes wrong if they are
|
|
| 908 | +mkInjectivityFDEqn qtvs inj_args lhs_args rhs_args
|
|
| 909 | + = assertPpr (let len = length inj_args in
|
|
| 910 | + len == length lhs_args && len == length rhs_args)
|
|
| 911 | + (vcat [ text "inj_args:" <+> ppr inj_args
|
|
| 912 | + , text "lhs_args:" <+> ppr lhs_args
|
|
| 913 | + , text "rhs_args:" <+> ppr rhs_args ]) $
|
|
| 914 | + -- Need inj_args lhs_args and rhs_args to be same length for zip3
|
|
| 915 | + FDEqns { fd_qtvs = qtvs, fd_eqs = eqs }
|
|
| 895 | 916 | where
|
| 896 | 917 | eqs = [ Pair lhs_arg rhs_arg
|
| 897 | 918 | | (True, lhs_arg, rhs_arg) <- zip3 inj_args lhs_args rhs_args ]
|
| ... | ... | @@ -1096,73 +1117,108 @@ Note [Exploiting closed type families]. |
| 1096 | 1117 | |
| 1097 | 1118 | Note [Exploiting open type families] see `mkTopOpenFamEqFDs`
|
| 1098 | 1119 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 1099 | -Generating fundeps from a top-level type instance is covered in Section 5.2 in
|
|
| 1100 | -the Injective Type Families paper. For open type families, suppose we have
|
|
| 1101 | - |
|
| 1102 | - type family F a = r | r -> a
|
|
| 1103 | - type instance F [a] = a->a
|
|
| 1104 | - |
|
| 1105 | - [W] F alpha ~ Int->Int
|
|
| 1106 | - |
|
| 1107 | -Then, since F has been checked as injective, and the RHS `a->a` (pre-)unifies
|
|
| 1108 | -with the `Int->Int` in the Wanted with substitution [a :-> Int], we can
|
|
| 1109 | -add a derived FunDepEqns
|
|
| 1120 | +For an open type family, generating fundeps from a top-level type instance
|
|
| 1121 | +is covered in Section 5.2 in the Injective Type Families paper.
|
|
| 1122 | + |
|
| 1123 | +Basic plan: Suppose type family F a b = r | r -> b
|
|
| 1124 | + and Wanted [W] F wlhs1 wlhs2 ~ wrhs
|
|
| 1125 | + Then for each type instance (F lhs1 lhs2 = rhs)
|
|
| 1126 | + * Pre-match `rhs` against `wrhs` to get a substitution S
|
|
| 1127 | + * Generate fundep equalities S(lhs2) ~ wrhs
|
|
| 1128 | + one for each fundep in the type family
|
|
| 1129 | + |
|
| 1130 | +For example, suppose we have
|
|
| 1131 | + type family F a b = r | r -> a
|
|
| 1132 | + type instance F [a] Int = a->a
|
|
| 1133 | + [W] F alpha beta ~ Int->Int
|
|
| 1134 | +Then we pre-match template (a->a) against target (Int->Int) to get
|
|
| 1135 | +substitution S = [a :-> Int]. Then we can generate
|
|
| 1110 | 1136 | FDEqns{ fd_qtvs = [], fd_eqs = [ [Int] ~ alpha ] }
|
| 1111 | 1137 | and thereby emit (via `instantiateFunDepEqns`)
|
| 1112 | 1138 | [W] [Int] ~ alpha
|
| 1139 | +Note that `fd_qtvs = []`; we have substituted away the quantifed type variable `a`.
|
|
| 1113 | 1140 | |
| 1114 | 1141 | Things are a bit trickier when not all the quantified variables of the
|
| 1115 | 1142 | instance are bound by the pre-unification step. Suppose we have
|
| 1116 | - |
|
| 1117 | 1143 | type family F a = r | r -> a
|
| 1118 | - type instance F (Maybe a) = [G a] -- G is a type family
|
|
| 1144 | + type instance F (b -> Maybe a) = [(G a,b)] -- G is a type family
|
|
| 1145 | + [W] F alpha ~ [(ty,Int)]
|
|
| 1119 | 1146 | |
| 1120 | - [W] F alpha ~ [ty]
|
|
| 1121 | - |
|
| 1122 | -Then, the RHS [G a] pre-unifies with the RHS of the Wanted, but with an
|
|
| 1123 | -empty substitution, which does not fix `a`. So we get this FunDepEqns:
|
|
| 1124 | - FDEqns{ fd_qtvs = a, fd_eqs = [ Maybe a ~ alpha ] }
|
|
| 1147 | +Then, the RHS [(G a,b)] pre-matches with the RHS of the Wanted, but with
|
|
| 1148 | +the substitution [b :-> Int], which does not fix `a`. So, after trimming
|
|
| 1149 | +the quantified type variables, we get this FunDepEqns:
|
|
| 1150 | + FDEqns{ fd_qtvs = [a], fd_eqs = [ (Int -> Maybe a) ~ alpha ] }
|
|
| 1125 | 1151 | (note the fd_qtvs=a) and thereby emit (via `instantiateFunDepEqns`)
|
| 1126 | - [W] Maybe gamma ~ alpha -- Fresh gamma
|
|
| 1127 | -We have learned that `alpha` must be a list, but that is all; we don't
|
|
| 1128 | -know what is inside it, hence the fresh `gamma`.
|
|
| 1129 | - |
|
| 1130 | -In general we have:
|
|
| 1131 | - |
|
| 1132 | - type family F x1 ... xn = r | r -> x1 x3 (say)
|
|
| 1133 | - type instance forall qs. F t1 ... tn = rhs
|
|
| 1134 | - [W] F a1 ... an ~ b
|
|
| 1135 | - |
|
| 1136 | -Suppose `b` pre-unifies with `rhs`, with substitution `S` that binds
|
|
| 1137 | -some (but perhaps not all) of the `qs`. Lets say
|
|
| 1138 | - unbound_qs = qs \ dom(S)
|
|
| 1139 | - |
|
| 1140 | -Then we generate the FunDepEqs
|
|
| 1141 | - FDEqns{ fd_qtvs = unbound_qs
|
|
| 1142 | - , fd_eqs = [ S(t1) ~ S(a1), S(t3) ~ S(a3) ]
|
|
| 1143 | - |
|
| 1144 | -These 'fd_qtvs' are subsequently instantiated to fresh metavariables by
|
|
| 1145 | -'instantiateFunDepEqns'.
|
|
| 1146 | - |
|
| 1147 | -(OF1) The computation of `unbound_qs` is done by `trim_qtvs`, but we
|
|
| 1148 | - have to be careful. Suppose (OF1a)
|
|
| 1149 | - qs = [ k::*, a::k ]
|
|
| 1150 | - S = [ k :-> UnliftedType ]
|
|
| 1151 | - Then we want
|
|
| 1152 | - unbound_qs = [ a::UnliftedType ] -- Must apply S to q's kind!!
|
|
| 1153 | - |
|
| 1154 | - And (OF1b), although I'm not sure if this can acutally happen:
|
|
| 1155 | - qs = [ k::*, a::(k::*), b::(a::k) ]
|
|
| 1156 | - S = [ k :-> UnliftedType ]
|
|
| 1157 | - We want
|
|
| 1158 | - unbound_qs = [ a::UnliftedType, b::(a::UnliftedType) ]
|
|
| 1159 | - Note that the occurrence of `a` in b's kind should be replaced by the
|
|
| 1160 | - newly-kinded `a` not the original `a::k`.
|
|
| 1161 | - |
|
| 1162 | - This fancy footwork for `fd_qtvs` is done by `trim_qtvs`. It
|
|
| 1163 | - * Drops a quantified tyvar that /is/ matched
|
|
| 1164 | - * Substitutes in the kind of a quantified tyvar `a` that is /not/ matched
|
|
| 1165 | - * Adds the substitution [a::k :-> a::S(k)] to the substitution
|
|
| 1152 | + [W] (Int -> Maybe gamma) ~ alpha -- Fresh gamma
|
|
| 1153 | +We have learned that `alpha` must be a list of functions, but that is all;
|
|
| 1154 | +we don't know `gamma`.
|
|
| 1155 | + |
|
| 1156 | +It gets tricker. Suppose we have
|
|
| 1157 | + type family F @k a = r | r -> k,a
|
|
| 1158 | + type instance F @k (Proxy @k (a::k)) = T k
|
|
| 1159 | + [W] F alpha beta ~ T Type
|
|
| 1160 | +Matching the RHS gives substitution [k :-> Type]. But we do /not/ want
|
|
| 1161 | +to end up with this:
|
|
| 1162 | + FDEqns{ fd_qtvs = [a::k], fd_eqs = [ Proxy @Type (a::k) ~ alpha ] }
|
|
| 1163 | +because that `k`, hidden inside the kind of `a`, escapes into the solver.
|
|
| 1164 | + |
|
| 1165 | +Instead we must not only "trim" the quantified variables of the equation,
|
|
| 1166 | +but /substitute/ in the kinds of the leftover quantified ones: see Note [trimQtvs].
|
|
| 1167 | +Then we get
|
|
| 1168 | + FDEqns{ fd_qtvs = [a::Type], fd_eqs = [ Proxy @Type (a::Type) ~ alpha ] }
|
|
| 1169 | + |
|
| 1170 | +Side note:
|
|
| 1171 | + |
|
| 1172 | +You might wonder whether we can use the same solution as we do for /closed/
|
|
| 1173 | +families, by generating an equality for the RHSs; see (CF7). But we can't.
|
|
| 1174 | +Example:
|
|
| 1175 | + type family G a where G Int = Char
|
|
| 1176 | + type family F a b = r | r -> a
|
|
| 1177 | + type instance F a [c] = (a, G a) -- (I1)
|
|
| 1178 | + type instance F Int Bool = (Int, Bool) -- (I2)
|
|
| 1179 | + [W] F alpha Bool ~ (Int,gamma)
|
|
| 1180 | +Note that (I1) and (I2) are pariwise-injective: if the RHSs are the same,
|
|
| 1181 | +the LHSs are the same /in the injective position(s)/. See Section 4.2 in
|
|
| 1182 | +the "Injective Type Families" paper. We pre-match (I1) against the Wanted
|
|
| 1183 | +giving substitution [a :-> Int]. We /cannot/ then generate
|
|
| 1184 | + FDEqns { fd_qtvs = [a,c], fd_eqs = [ a~alpha
|
|
| 1185 | + , (a,G a)~(Int,gamma) ] }
|
|
| 1186 | +where the second equality (wrongly)equates the RHSs. This is wrong because we
|
|
| 1187 | +can solve those fundeps unifying alpha:=Int, gamma:=Char, by reducing (G a) to
|
|
| 1188 | +Char. So we end up with [W] F Int Char, which is insoluble. Bad.
|
|
| 1189 | + |
|
| 1190 | +End of side note.
|
|
| 1191 | + |
|
| 1192 | +Note [trimQtvs]
|
|
| 1193 | +~~~~~~~~~~~~~~~
|
|
| 1194 | +In Note [Exploiting open type families], we needed to "trim" the quantified
|
|
| 1195 | +type variables of the axiom, removing ones that are eliminated by the
|
|
| 1196 | +auubstitution `S`. So can we just do this?
|
|
| 1197 | + unbound_qs = qs \ dom(S)
|
|
| 1198 | +so that we could make fresh meta-variables for only the unbound `qs`.
|
|
| 1199 | +No, we can't. Suppose (TQ1)
|
|
| 1200 | + qs = [ k::*, a::k ]
|
|
| 1201 | + S = [ k :-> UnliftedType ]
|
|
| 1202 | +Then we want
|
|
| 1203 | + unbound_qs = [ a::UnliftedType ] -- Must apply S to q's kind!!
|
|
| 1204 | + |
|
| 1205 | +And (TQ2), although I'm not sure if this can actually happen:
|
|
| 1206 | + qs = [ k::*, a::(k::*), b::(a::k) ]
|
|
| 1207 | + S = [ k :-> UnliftedType ]
|
|
| 1208 | +We want
|
|
| 1209 | + unbound_qs = [ a::UnliftedType, b::(a::UnliftedType) ]
|
|
| 1210 | +Note that the occurrence of `a` in b's kind should be replaced by the
|
|
| 1211 | +newly-kinded `a` not the original `a::k`.
|
|
| 1212 | + |
|
| 1213 | +The function `trimQtvs` does the job. It
|
|
| 1214 | + * Drops a quantified tyvar that /is/ matched
|
|
| 1215 | + * Substitutes in the kind of a quantified tyvar `a` that is /not/ matched
|
|
| 1216 | + * Adds the substitution [a::k :-> a::S(k)] to the substitution
|
|
| 1217 | + |
|
| 1218 | +We only use `trimQtvs` for /open/ families. For /closed/ families where we
|
|
| 1219 | +/unify/ (rather than match) the equation with the Wanted, it just doesn't work
|
|
| 1220 | +(#27994), because the substitution `S` has both meta-tyvars and instance-head
|
|
| 1221 | +tyvars in the range. See (CF7).
|
|
| 1166 | 1222 | |
| 1167 | 1223 | Note [Exploiting closed type families] see `mkTopClosedFamEqFDs`
|
| 1168 | 1224 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1194,9 +1250,6 @@ More precisely, here is the very clever Closed Family Fundep Algorithm (CFFA) |
| 1194 | 1250 | with fresh unification vars in lhs and rhs for the quantified variables of the
|
| 1195 | 1251 | equation.
|
| 1196 | 1252 | |
| 1197 | - Actually we take advantage of the substitution generated by the relevance
|
|
| 1198 | - check, see (CF7) below.
|
|
| 1199 | - |
|
| 1200 | 1253 | See Note [Relevance] for what "relevant" means.
|
| 1201 | 1254 | We need to take care about non-termination; see (CF3).
|
| 1202 | 1255 | |
| ... | ... | @@ -1303,7 +1356,7 @@ Key point: equations that are not relevant do not need to be considered for fund |
| 1303 | 1356 | I was looking at non-termination for closed type families, but it's a small
|
| 1304 | 1357 | improvement in general.
|
| 1305 | 1358 | |
| 1306 | - This bale-out is implementedn in `tryFDEqns`.
|
|
| 1359 | + This bale-out is implemented in `tryFDEqns`.
|
|
| 1307 | 1360 | |
| 1308 | 1361 | (CF5) Consider (see "Yikes5" in #23162):
|
| 1309 | 1362 | type family F a where
|
| ... | ... | @@ -1353,32 +1406,20 @@ Key point: equations that are not relevant do not need to be considered for fund |
| 1353 | 1406 | `app` Proxy @'[ty_n]
|
| 1354 | 1407 | |
| 1355 | 1408 | Every `app` call gives rise to a Wanted of the form:
|
| 1356 | - |
|
| 1357 | 1409 | [W] MapId acc_i ++ MapId '[ty_i] ~ MapId (acc_i ++ '[ty_i])
|
| 1358 | - |
|
| 1359 | 1410 | while the overall result type gives us a Wanted of the form
|
| 1360 | - |
|
| 1361 | 1411 | [W] acc_n ++ '[ty_n] ~ [ty_1, ..., ty_n]
|
| 1362 | - |
|
| 1363 | 1412 | By using (CFFA) on this result Wanted, we deduce that we must have
|
| 1364 | - |
|
| 1365 | 1413 | acc_n ~ [ty_1, ..., ty_{n-1}]
|
| 1366 | - |
|
| 1367 | 1414 | which is a flat list. Repeating the process, (CFFA) allows us to deduce that
|
| 1368 | - |
|
| 1369 | 1415 | acc_i ~ [ty_1, ..., ty_{i-1}]
|
| 1370 | - |
|
| 1371 | 1416 | for all i. This allows the other Wanteds to be solved directly, giving rise to
|
| 1372 | 1417 | proof terms with the typical triangular O(n^2) shape
|
| 1373 | - |
|
| 1374 | 1418 | co_i = (O(i) proof that MapId acc_i ++ MapId '[ty_i] ~ acc_{i+1})
|
| 1375 | 1419 | ; (O(i) proof that acc_{i+1} ~ MapId (acc_i ++ '[ty_i]))
|
| 1376 | - |
|
| 1377 | 1420 | However, /without/ (CFFA), 'acc_i' is not unified with a flat list but is left
|
| 1378 | 1421 | as the nested application:
|
| 1379 | - |
|
| 1380 | 1422 | acc_i ~ (... (('[ty_1] ++ '[ty_2]) ++ '[ty_3]) ... ++ '[ty_{i-1}])
|
| 1381 | - |
|
| 1382 | 1423 | This means that 'MapId acc_i' is stuck until we reduce the above, which takes
|
| 1383 | 1424 | O(i^2) type family reduction steps, instead of O(i). The same applies to
|
| 1384 | 1425 | the other proof term involving 'MapId (acc_i ++ '[ty_i])'.
|
| ... | ... | @@ -1388,29 +1429,77 @@ Key point: equations that are not relevant do not need to be considered for fund |
| 1388 | 1429 | instead of relying on recursively built sub-proof terms, which brings down
|
| 1389 | 1430 | coercion sizes (in certain situations) from O(n^3) to O(n^2).
|
| 1390 | 1431 | |
| 1391 | -(CF7) Relevance. When computing relevance in the Closed Family Fundep Algorithm,
|
|
| 1392 | - for [W] F wlhs1 wlhs2 ~ wrhs, against an equation F lhs1 lhs2 ~ rhs
|
|
| 1393 | - we get back a pre-unifying substitution S that makes the two as equal as poss.
|
|
| 1394 | - Then we use `trim_qtvs` in exactly the same way as in
|
|
| 1395 | - (OF1) of Note [Exploiting open type families], to generate qtvs' and S'
|
|
| 1396 | - Then we generate
|
|
| 1397 | - FDEqns { fd_qtvs = qtvs', fd_eqs [ S'(lhs1) ~ wlhs1
|
|
| 1398 | - , S'(lhs2) ~ wlhs2
|
|
| 1399 | - , S'(rhs) ~ wrhs ] }
|
|
| 1400 | - Notice that we do /not/ apply S' to wlhs/wrhs. These type contain unification
|
|
| 1401 | - variables that we must actually unify! Example
|
|
| 1432 | +(CF7) Relevance. The function `getRelevantBranches` finds the relevant branch(es)
|
|
| 1433 | + using the (CFFA). Given an equation
|
|
| 1434 | + type family F a b where { ...; F lhs1 lhs2 = rhs; ... }
|
|
| 1435 | + is the equation relevant for this Wanted?
|
|
| 1436 | + [W] F wlhs1 wlhs2 ~ wrhs
|
|
| 1437 | + We pre-unify [wrhs,wlhs1,wlhs2] against [rhs,lhs1,lhs2], getting back a
|
|
| 1438 | + substitution `S` that makes the two as equal as poss. This substitution can bind
|
|
| 1439 | + both /quantified/ type variables from the instance, and /unification variables/
|
|
| 1440 | + from the solver. Moreover, both kind of type variable can appear in the range
|
|
| 1441 | + of the substitution.
|
|
| 1442 | + |
|
| 1443 | + That's pretty complicated, so we are very cautious about using the returned
|
|
| 1444 | + substitution `S`. I had a long struggle (#27994) when we were previously trying to
|
|
| 1445 | + apply that returned substitution as an optimisation. But because type variables
|
|
| 1446 | + can occur in kinds, it was a losing battle -- I ended up with TyVars from the
|
|
| 1447 | + instance head escaping into the solver. Consider
|
|
| 1448 | + type F :: forall k. k -> *
|
|
| 1449 | + type instance F k a where
|
|
| 1450 | + F (k->*) (b::k->*) = Int
|
|
| 1451 | + [W] F kappa (alpha::kappa) ~ Int
|
|
| 1452 | + We unify the Wanted with the equation to get the substitution
|
|
| 1453 | + [ kappa :-> k->*, b :-> (alpha::k->*) ]
|
|
| 1454 | + I tried using `trimQtvs` (see Note [trimQtvs]) but my head hurt
|
|
| 1455 | + FAR too much: #27994 is an excellent example.
|
|
| 1456 | + |
|
| 1457 | + So here's the plan:
|
|
| 1458 | + (A) As a fast-path optimisation, if `S` binds all the quantified variables of
|
|
| 1459 | + the type-family equation (which is common), it's all easy: generate
|
|
| 1460 | + FDEqns { fd_qtvs = []
|
|
| 1461 | + , fd_eqs = [ S(lhs1) ~ wlhs1, S(lhs2) ~ wlhs2, S(rhs) ~ wrhs }
|
|
| 1462 | + Note that we do not apply S to `wlhs1/2` or `wrhs`; see (CF9).
|
|
| 1463 | + And note that `fd_qtvs` is empty, because `S` eliminates all the quantified
|
|
| 1464 | + type variables.
|
|
| 1465 | + |
|
| 1466 | + (B) If not, then /discard `S` entirely/ and instead generate
|
|
| 1467 | + FDEqns { fd_qtvs = qtvs
|
|
| 1468 | + , fd_eqs = [ lhs ~ wlhs1, lhs2 ~ wlhs2, rhs ~ wrhs }
|
|
| 1469 | + Now `instantiateFDEqns` will generate fresh unification variables for the
|
|
| 1470 | + `qtvs` and the solver will in effect reconstruct `S`.
|
|
| 1471 | + |
|
| 1472 | +(CF8) When computing relevance (Note [Relevance] (R2)) we use `noEarlierMatch`
|
|
| 1473 | + on S(lhs). But we must use /deep/ substitution on LHS. Consider
|
|
| 1474 | + type family F (a :: k) r where
|
|
| 1475 | + F @Type (Maybe Bool) r = r -- B0
|
|
| 1476 | + F @Type ((f :: Type -> Type) Int) r = Bool -- B1
|
|
| 1477 | + F @k ((g :: Type -> k) Int) r = r -- B2
|
|
| 1478 | + |
|
| 1479 | + [W] F @Type alpha Char ~ Char
|
|
| 1480 | + The `tcUnifyTysForInjectivity` will return substitution
|
|
| 1481 | + [k :-> Type, r :-> Char, alpha :-> (g :: Type->Type) Int], with g unbound
|
|
| 1482 | + If we used `substTy` on the LHS-tys for B2 we'd get
|
|
| 1483 | + lhs_tys' = [Type, (g :: Type -> k) Int, Char]
|
|
| 1484 | + That's ill-kinded because of the free `k`; and (worse) when `noEarlierMatch` matches
|
|
| 1485 | + lhs_tys' against earlier equations, (B1) will fail to match. So (B2) will be
|
|
| 1486 | + judged relevant, even though it isn't. Bad, bad. Use deep substitution.
|
|
| 1487 | + |
|
| 1488 | +(CF9) Notice that, in (CF7) when generating the fundep equations for the solver to
|
|
| 1489 | + deal with, we do /not/ apply the pre-unifying substitution `S` to the Wanted types.
|
|
| 1490 | + The types wlhs,wrhs contain meta-variables that we must actually unify! Example
|
|
| 1402 | 1491 | type family F a b where
|
| 1403 | 1492 | F [a] (Maybe b) = (a, G b)
|
| 1404 | 1493 | [W] F alpha beta ~ (Int, [gamma])
|
| 1405 | 1494 | Pre-unification gives [alpha :-> [a], beta :-> Maybe b, a :-> Int]
|
| 1406 | - This substitution eliminates the quantified variable `a` but not `b`, so we
|
|
| 1407 | - want this:
|
|
| 1408 | - FDEqns { fd_qtvs = [b], fd_eqs [ [Int] ~ alpha
|
|
| 1409 | - , Maybe b ~ beta
|
|
| 1410 | - , (Int,G b) ~ (Int, [gamma]) ] }
|
|
| 1411 | - |
|
| 1412 | - Notice also that by applying the substitution to the template but not to the
|
|
| 1413 | - Wanted, we uphold the `fd_eqs` invariant in `FDEqns` (see its data type decl)
|
|
| 1495 | + We don't want to substitute `alpha` away! In fact we just generate these eqns:
|
|
| 1496 | + FDEqns { fd_qtvs = [a,b], fd_eqs [ [a] ~ alpha
|
|
| 1497 | + , Maybe b ~ beta
|
|
| 1498 | + , (a, G b) ~ (Int, [gamma]) ] }
|
|
| 1499 | + with `fd_qtvs` being the quantified variables of the equation, the LHSs
|
|
| 1500 | + being the types from the equation and the RHSs being the types from the Wanted.
|
|
| 1501 | + Notice that we thereby uphold the `fd_eqs` invariant in `FDEqns` (see its data
|
|
| 1502 | + type decl).
|
|
| 1414 | 1503 | |
| 1415 | 1504 | Note [Cache-caused loops]
|
| 1416 | 1505 | ~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1517,8 +1606,8 @@ instantiateFunDepEqns (FDEqns { fd_qtvs = qtvs, fd_eqs = eqs }) |
| 1517 | 1606 | rev_eqs = reverse eqs
|
| 1518 | 1607 | -- (reverse eqs): See Note [Reverse order of fundep equations]
|
| 1519 | 1608 | |
| 1520 | - -- The kinds of `qtvs` can have free variables, because of `trim_qtvs`
|
|
| 1521 | - -- Example: T27828b
|
|
| 1609 | + -- The kinds of `qtvs` can have free variables;
|
|
| 1610 | + -- in the FDEqns produced by GHC.Tc.Instance.FunDeps.improveFromInstEnv
|
|
| 1522 | 1611 | empty_subst = mkEmptySubst $ mkInScopeSet $
|
| 1523 | 1612 | tyCoVarsOfTypes (map tyVarKind qtvs)
|
| 1524 | 1613 |
| ... | ... | @@ -61,7 +61,6 @@ import GHC.Prelude |
| 61 | 61 | |
| 62 | 62 | import GHC.Hs
|
| 63 | 63 | import GHC.Tc.Errors.Types ( HsCtxt(..) )
|
| 64 | -import GHC.Tc.Errors.Ppr ( pprHsCtxt )
|
|
| 65 | 64 | import GHC.Tc.Utils.Concrete
|
| 66 | 65 | import GHC.Tc.Utils.Env
|
| 67 | 66 | import GHC.Tc.Utils.Instantiate
|
| ... | ... | @@ -2801,17 +2800,15 @@ uType_defer (UE { u_loc = loc, u_defer = ref |
| 2801 | 2800 | -- snocBag: see Note [Work-list ordering] in GHC.Tc.Solver.Equality
|
| 2802 | 2801 | |
| 2803 | 2802 | -- Error trace only
|
| 2804 | - -- NB. do *not* call tidyErrCtxt unless tracing is on,
|
|
| 2805 | - -- because it is hugely expensive (#5631)
|
|
| 2803 | + -- NB. do *not* call tidyErrCtxt because
|
|
| 2804 | + -- (a) it is hugely expensive (#5631) and
|
|
| 2805 | + -- (b) it crashes in some cases because because it reads
|
|
| 2806 | + -- res_ty too early via FunResCtxt and getCheckExpType
|
|
| 2806 | 2807 | ; whenDOptM Opt_D_dump_tc_trace $
|
| 2807 | - do { ctxt <- getErrCtxt
|
|
| 2808 | - ; err_ctxt <- tidyErrCtxt emptyTidyEnv ctxt
|
|
| 2809 | - ; traceTc "utype_defer" $
|
|
| 2810 | - vcat ( ppr role
|
|
| 2811 | - : debugPprType ty1
|
|
| 2812 | - : debugPprType ty2
|
|
| 2813 | - : map pprHsCtxt err_ctxt )
|
|
| 2814 | - ; traceTc "utype_defer2" (ppr co) }
|
|
| 2808 | + traceTc "utype_defer" $
|
|
| 2809 | + vcat [ text "role:" <+> ppr role
|
|
| 2810 | + , text "ty1:" <+> debugPprType ty1
|
|
| 2811 | + , text "ty2:" <+> debugPprType ty2 ]
|
|
| 2815 | 2812 | |
| 2816 | 2813 | ; return co }
|
| 2817 | 2814 |
| ... | ... | @@ -229,9 +229,17 @@ uniqAway' in_scope var |
| 229 | 229 | -- | @unsafeGetFreshUnique in_scope@ finds a unique that is not in-scope in the
|
| 230 | 230 | -- given 'InScopeSet'. This must be used very carefully since one can very easily
|
| 231 | 231 | -- introduce non-unique 'Unique's this way. See Note [Local uniques].
|
| 232 | +--
|
|
| 233 | +-- Despite its name, there is nothing unsafe about it, provided you
|
|
| 234 | +-- know that all it does is find a unique not in the in-scope set.
|
|
| 235 | +-- Two calls with the same in-scope set will (of course) produce the
|
|
| 236 | +-- same unique.
|
|
| 232 | 237 | unsafeGetFreshLocalUnique :: InScopeSet -> Unique
|
| 233 | 238 | unsafeGetFreshLocalUnique (InScope set)
|
| 234 | 239 | | Just (uniq,_) <- Word64Map.lookupLT (getKey maxLocalUnique) (ufmToIntMap $ getUniqSet set)
|
| 240 | + -- (lookupLT k m) finds the largest (key,value) in `m` such that key < k
|
|
| 241 | + -- So if we make k=maxLocalUnique we'll just get the largest key in `m`
|
|
| 242 | + -- Then all we need do is increment it, and that'll give us a fresh one
|
|
| 235 | 243 | , let uniq' = mkLocalUnique uniq
|
| 236 | 244 | , not $ uniq' `ltUnique` minLocalUnique
|
| 237 | 245 | = incrUnique uniq'
|
| 1 | +{-# LANGUAGE AllowAmbiguousTypes #-}
|
|
| 2 | +{-# LANGUAGE DataKinds #-}
|
|
| 3 | +{-# LANGUAGE FunctionalDependencies #-}
|
|
| 4 | +{-# LANGUAGE GADTs #-}
|
|
| 5 | +{-# LANGUAGE TypeFamilies #-}
|
|
| 6 | +module T27994a (l2) where
|
|
| 7 | + |
|
| 8 | +import Data.Kind (Constraint, Type)
|
|
| 9 | + |
|
| 10 | +l1 :: [String]
|
|
| 11 | +l1 = ["hello", "world!"]
|
|
| 12 | + |
|
| 13 | +l2 :: [Int]
|
|
| 14 | +l2 = gmap (HCons length HNil) l1
|
|
| 15 | + |
|
| 16 | +-----
|
|
| 17 | + |
|
| 18 | +type HList :: [Type] -> Type
|
|
| 19 | +data HList p where
|
|
| 20 | + HNil :: HList '[]
|
|
| 21 | + HCons :: x -> HList xs -> HList (x:xs)
|
|
| 22 | + |
|
| 23 | +type ($$) :: k -> [Type] -> Type
|
|
| 24 | +type family s $$ p where
|
|
| 25 | + (s :: Type) $$ '[] = s
|
|
| 26 | + (s :: Type -> k) $$ (a:b) = s a $$ b
|
|
| 27 | + |
|
| 28 | +type Doms :: [Type] -> [Type]
|
|
| 29 | +type family Doms t where
|
|
| 30 | + Doms '[] = '[]
|
|
| 31 | + Doms ((a -> b) : t) = a : Doms t
|
|
| 32 | + |
|
| 33 | +type Codoms :: [Type] -> [Type]
|
|
| 34 | +type family Codoms t where
|
|
| 35 | + Codoms '[] = '[]
|
|
| 36 | + Codoms ((a -> b) : t) = b : Codoms t
|
|
| 37 | + |
|
| 38 | +type GMap :: k -> [Type] -> Constraint
|
|
| 39 | +class GMap (s :: k) t | t -> k where
|
|
| 40 | + gmap :: HList t -> s $$ Doms t -> s $$ Codoms t
|
|
| 41 | + |
|
| 42 | +instance GMap [] '[a -> b] where
|
|
| 43 | + gmap :: HList '[a -> b] -> [a] -> [b]
|
|
| 44 | + gmap (HCons f HNil) = go
|
|
| 45 | + where
|
|
| 46 | + go :: [a] -> [b]
|
|
| 47 | + go [] = []
|
|
| 48 | + go (x:xs) = f x : go xs |
| 1 | +{-# LANGUAGE DataKinds, TypeFamilies, PolyKinds, GADTs, AllowAmbiguousTypes #-}
|
|
| 2 | +module T27994 where
|
|
| 3 | + |
|
| 4 | +import Data.Kind (Type)
|
|
| 5 | +import Data.Proxy (Proxy)
|
|
| 6 | + |
|
| 7 | +type F :: forall{k}. k -> Type -> Type
|
|
| 8 | +type family F s x where
|
|
| 9 | + F (s :: Type -> k) (Proxy s) = Int
|
|
| 10 | + |
|
| 11 | +f :: forall k (s :: k) x. F s x -> x
|
|
| 12 | +f _ = undefined
|
|
| 13 | + |
|
| 14 | +g :: Proxy Maybe -> ()
|
|
| 15 | +g _ = ()
|
|
| 16 | + |
|
| 17 | +data T a where
|
|
| 18 | + MkT :: T Int
|
|
| 19 | + |
|
| 20 | +test :: T a -> ()
|
|
| 21 | +test t = (\y -> case t of MkT -> g y) (f (3 :: Int))
|
|
| 22 | + |
|
| 23 | +{- [W] F @k_azX (s_azY::k_azX) p_azN ~ Int
|
|
| 24 | + |
|
| 25 | +unify [*->k, s::*->k, Proxy @(*->k) (s::*->k), Int]
|
|
| 26 | + ~ [k_azX, s_azY::k_azX, p_azN, Int]
|
|
| 27 | + |
|
| 28 | + --> [ k_azX :-> (* -> k)
|
|
| 29 | + , s :-> s_azY::k_azX
|
|
| 30 | + , p_azN :-> Proxy @(*->k) (s::*->k) ]
|
|
| 31 | + |
|
| 32 | + fixpt --> [ k_azX :-> Type -> k
|
|
| 33 | + , s :-> s_azY::(Type -> k)
|
|
| 34 | + , p_azN :-> Proxy @(Type->k) (s::k_azX) ]
|
|
| 35 | + |
|
| 36 | +Generate a [W] for each pair
|
|
| 37 | + [W] k ~ k_azX
|
|
| 38 | + [W] s ~ s_azY
|
|
| 39 | + [W] Proxy s ~ p_azN
|
|
| 40 | + [W] Int ~ Int
|
|
| 41 | +As an opt (claim) apply subst first
|
|
| 42 | + [W] k_azX ~ k_azX
|
|
| 43 | + [W] s_azY ~ s_azY
|
|
| 44 | + [W] Proxy s_azY ~ p_azN
|
|
| 45 | + [W] Int ~ Int
|
|
| 46 | + |
|
| 47 | +-- [W] F @k_azX s_azY[tau] p_azN ~ Int
|
|
| 48 | +-- Want: fresh k' s'
|
|
| 49 | +-- [W] k' ~ k_azX
|
|
| 50 | +-- [W] s':k' ~ s_azY:k_azX
|
|
| 51 | +-- [W] Proxy s' ~ x
|
|
| 52 | +-}
|
|
| 53 | + |
| 1 | +{-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-}
|
|
| 2 | + |
|
| 3 | + |
|
| 4 | +module T27994b where
|
|
| 5 | +import Data.Proxy
|
|
| 6 | + |
|
| 7 | +type family G a where G Int = Char
|
|
| 8 | +type family F a b = r | r -> a
|
|
| 9 | +type instance F a [c] = (a, G a) -- instance 1
|
|
| 10 | +type instance F Int Bool = (Int, Bool) -- instance 2
|
|
| 11 | + |
|
| 12 | +h :: Proxy a -> F a Bool
|
|
| 13 | +h = h
|
|
| 14 | +k :: (Int, b) -> b
|
|
| 15 | +k = k
|
|
| 16 | + |
|
| 17 | +test = k (h Proxy) `seq` () -- [W] F alpha Bool ~ (Int, gamma) |
| ... | ... | @@ -972,4 +972,6 @@ test('T27557', normal, compile, ['']) |
| 972 | 972 | test('T27664', normal, compile, [''])
|
| 973 | 973 | test('T27916', normal, compile, [''])
|
| 974 | 974 | test('T26543_orig', normal, compile, [''])
|
| 975 | - |
|
| 975 | +test('T27994', normal, compile, [''])
|
|
| 976 | +test('T27994a', normal, compile, [''])
|
|
| 977 | +test('T27994b', normal, compile, ['']) |