diff options
author | Ryan Scott <ryan.gl.scott@gmail.com> | 2020-05-25 16:11:10 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2020-06-13 15:58:37 -0400 |
commit | a31218f7737a65b6333ec7905e88dc094703f025 (patch) | |
tree | ac5c9a2a8161da0c44605ac4d7ffe5df1719461c /compiler/GHC/Tc/Gen | |
parent | 7a773f169cfe072c7b29924c53075e4dfa4e2adb (diff) | |
download | haskell-a31218f7737a65b6333ec7905e88dc094703f025.tar.gz |
Use HsForAllTelescope to avoid inferred, visible foralls
Currently, `HsForAllTy` permits the combination of `ForallVis` and
`Inferred`, but you can't actually typecheck code that uses it
(e.g., `forall {a} ->`). This patch refactors `HsForAllTy` to use a
new `HsForAllTelescope` data type that makes a type-level distinction
between visible and invisible `forall`s such that visible `forall`s
do not track `Specificity`. That part of the patch is actually quite
small; the rest is simply changing consumers of `HsType` to
accommodate this new type.
Fixes #18235. Bumps the `haddock` submodule.
Diffstat (limited to 'compiler/GHC/Tc/Gen')
-rw-r--r-- | compiler/GHC/Tc/Gen/HsType.hs | 80 | ||||
-rw-r--r-- | compiler/GHC/Tc/Gen/Sig.hs | 10 | ||||
-rw-r--r-- | compiler/GHC/Tc/Gen/Splice.hs | 30 |
3 files changed, 64 insertions, 56 deletions
diff --git a/compiler/GHC/Tc/Gen/HsType.hs b/compiler/GHC/Tc/Gen/HsType.hs index e6cad5f4f0..b99cc6365b 100644 --- a/compiler/GHC/Tc/Gen/HsType.hs +++ b/compiler/GHC/Tc/Gen/HsType.hs @@ -896,11 +896,10 @@ tc_hs_type mode (HsOpTy _ ty1 (L _ op) ty2) exp_kind = tc_fun_type mode ty1 ty2 exp_kind --------- Foralls -tc_hs_type mode forall@(HsForAllTy { hst_fvf = fvf, hst_bndrs = hs_tvs - , hst_body = ty }) exp_kind - = do { (tclvl, wanted, (inv_tv_bndrs, ty')) - <- pushLevelAndCaptureConstraints $ - bindExplicitTKBndrs_Skol_M mode hs_tvs $ +tc_hs_type mode forall@(HsForAllTy { hst_tele = tele, hst_body = ty }) exp_kind + = do { (tclvl, wanted, (tv_bndrs, ty')) + <- pushLevelAndCaptureConstraints $ + bindExplicitTKTele_Skol_M mode tele $ -- The _M variant passes on the mode from the type, to -- any wildards in kind signatures on the forall'd variables -- e.g. f :: _ -> Int -> forall (a :: _). blah @@ -909,31 +908,27 @@ tc_hs_type mode forall@(HsForAllTy { hst_fvf = fvf, hst_bndrs = hs_tvs -- Do not kind-generalise here! See Note [Kind generalisation] - ; let skol_info = ForAllSkol (ppr forall) (sep (map ppr hs_tvs)) - skol_tvs = binderVars inv_tv_bndrs + ; let skol_info = ForAllSkol (ppr forall) $ sep $ case tele of + HsForAllVis { hsf_vis_bndrs = hs_tvs } -> + map ppr hs_tvs + HsForAllInvis { hsf_invis_bndrs = hs_tvs } -> + map ppr hs_tvs + tv_bndrs' = construct_bndrs tv_bndrs + skol_tvs = binderVars tv_bndrs' ; implic <- buildTvImplication skol_info skol_tvs tclvl wanted ; emitImplication implic -- /Always/ emit this implication even if wanted is empty -- We need the implication so that we check for a bad telescope -- See Note [Skolem escape and forall-types] - ; tv_bndrs <- mapM construct_bndr inv_tv_bndrs - ; return (mkForAllTys tv_bndrs ty') } + ; return (mkForAllTys tv_bndrs' ty') } where - construct_bndr :: TcInvisTVBinder -> TcM TcTyVarBinder - construct_bndr (Bndr tv spec) = do { argf <- spec_to_argf spec - ; return $ mkTyVarBinder argf tv } - - -- See Note [Variable Specificity and Forall Visibility] - spec_to_argf :: Specificity -> TcM ArgFlag - spec_to_argf SpecifiedSpec = case fvf of - ForallVis -> return Required - ForallInvis -> return Specified - spec_to_argf InferredSpec = case fvf of - ForallVis -> do { addErrTc (hang (text "Unexpected inferred variable in visible forall binder:") - 2 (ppr forall)) - ; return Required } - ForallInvis -> return Inferred + construct_bndrs :: Either [TcReqTVBinder] [TcInvisTVBinder] + -> [TcTyVarBinder] + construct_bndrs (Left req_tv_bndrs) = + map (mkTyVarBinder Required . binderVar) req_tv_bndrs + construct_bndrs (Right inv_tv_bndrs) = + map tyVarSpecToBinder inv_tv_bndrs tc_hs_type mode (HsQualTy { hst_ctxt = ctxt, hst_body = rn_ty }) exp_kind | null (unLoc ctxt) @@ -1068,21 +1063,21 @@ tc_hs_type mode ty@(HsWildCardTy _) ek = tcAnonWildCardOcc mode ty ek {- Note [Variable Specificity and Forall Visibility] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A HsForAllTy contains a ForAllVisFlag to denote the visibility of the forall -binder. Furthermore, each bound variable also has a Specificity. Together these -determine the variable binders (ArgFlag) for each variable in the generated -ForAllTy type. +A HsForAllTy contains an HsForAllTelescope to denote the visibility of the forall +binder. Furthermore, each invisible type variable binder also has a +Specificity. Together, these determine the variable binders (ArgFlag) for each +variable in the generated ForAllTy type. This table summarises this relation: --------------------------------------------------------------------------- -| User-written type ForAllVisFlag Specificity ArgFlag -|------------------------------------------------------------------------- -| f :: forall a. type ForallInvis SpecifiedSpec Specified -| f :: forall {a}. type ForallInvis InferredSpec Inferred -| f :: forall a -> type ForallVis SpecifiedSpec Required -| f :: forall {a} -> type ForallVis InferredSpec / +---------------------------------------------------------------------------- +| User-written type HsForAllTelescope Specificity ArgFlag +|--------------------------------------------------------------------------- +| f :: forall a. type HsForAllInvis SpecifiedSpec Specified +| f :: forall {a}. type HsForAllInvis InferredSpec Inferred +| f :: forall a -> type HsForAllVis SpecifiedSpec Required +| f :: forall {a} -> type HsForAllVis InferredSpec / | This last form is non-sensical and is thus rejected. --------------------------------------------------------------------------- +---------------------------------------------------------------------------- For more information regarding the interpretation of the resulting ArgFlag, see Note [VarBndrs, TyCoVarBinders, TyConBinders, and visibility] in "GHC.Core.TyCo.Rep". @@ -2863,6 +2858,21 @@ cloneFlexiKindedTyVarTyVar = newFlexiKindedTyVar cloneTyVarTyVar -- Explicit binders -------------------------------------- +-- | Skolemise the 'HsTyVarBndr's in an 'LHsForAllTelescope. +-- Returns 'Left' for visible @forall@s and 'Right' for invisible @forall@s. +bindExplicitTKTele_Skol_M + :: TcTyMode + -> HsForAllTelescope GhcRn + -> TcM a + -> TcM (Either [TcReqTVBinder] [TcInvisTVBinder], a) +bindExplicitTKTele_Skol_M mode tele thing_inside = case tele of + HsForAllVis { hsf_vis_bndrs = bndrs } -> do + (req_tv_bndrs, thing) <- bindExplicitTKBndrs_Skol_M mode bndrs thing_inside + pure (Left req_tv_bndrs, thing) + HsForAllInvis { hsf_invis_bndrs = bndrs } -> do + (inv_tv_bndrs, thing) <- bindExplicitTKBndrs_Skol_M mode bndrs thing_inside + pure (Right inv_tv_bndrs, thing) + bindExplicitTKBndrs_Skol, bindExplicitTKBndrs_Tv :: (OutputableBndrFlag flag) => [LHsTyVarBndr flag GhcRn] diff --git a/compiler/GHC/Tc/Gen/Sig.hs b/compiler/GHC/Tc/Gen/Sig.hs index 2ac2823fb5..df0c7d37f6 100644 --- a/compiler/GHC/Tc/Gen/Sig.hs +++ b/compiler/GHC/Tc/Gen/Sig.hs @@ -279,8 +279,8 @@ no_anon_wc lty = go lty HsRecTy _ flds -> gos $ map (cd_fld_type . unLoc) flds HsExplicitListTy _ _ tys -> gos tys HsExplicitTupleTy _ tys -> gos tys - HsForAllTy { hst_bndrs = bndrs - , hst_body = ty } -> no_anon_wc_bndrs bndrs + HsForAllTy { hst_tele = tele + , hst_body = ty } -> no_anon_wc_tele tele && go ty HsQualTy { hst_ctxt = L _ ctxt , hst_body = ty } -> gos ctxt && go ty @@ -293,8 +293,10 @@ no_anon_wc lty = go lty gos = all go -no_anon_wc_bndrs :: [LHsTyVarBndr flag GhcRn] -> Bool -no_anon_wc_bndrs ltvs = all (go . unLoc) ltvs +no_anon_wc_tele :: HsForAllTelescope GhcRn -> Bool +no_anon_wc_tele tele = case tele of + HsForAllVis { hsf_vis_bndrs = ltvs } -> all (go . unLoc) ltvs + HsForAllInvis { hsf_invis_bndrs = ltvs } -> all (go . unLoc) ltvs where go (UserTyVar _ _ _) = True go (KindedTyVar _ _ _ ki) = no_anon_wc ki diff --git a/compiler/GHC/Tc/Gen/Splice.hs b/compiler/GHC/Tc/Gen/Splice.hs index 3a4d0de24f..140299997a 100644 --- a/compiler/GHC/Tc/Gen/Splice.hs +++ b/compiler/GHC/Tc/Gen/Splice.hs @@ -2123,19 +2123,19 @@ reifyType ty@(CoercionTy {})= noTH (sLit "coercions in types") (ppr ty) reify_for_all :: TyCoRep.ArgFlag -> TyCoRep.Type -> TcM TH.Type -- Arg of reify_for_all is always ForAllTy or a predicate FunTy -reify_for_all argf ty = do - tvbndrs' <- reifyTyVarBndrs tvbndrs - case argToForallVisFlag argf of - ForallVis -> do phi' <- reifyType phi - let tvs = map (() <$) tvbndrs' - -- see Note [Specificity in HsForAllTy] in GHC.Hs.Type - pure $ TH.ForallVisT tvs phi' - ForallInvis -> do let (cxt, tau) = tcSplitPhiTy phi - cxt' <- reifyCxt cxt - tau' <- reifyType tau - pure $ TH.ForallT tvbndrs' cxt' tau' - where - (tvbndrs, phi) = tcSplitForAllTysSameVis argf ty +reify_for_all argf ty + | isVisibleArgFlag argf + = do let (req_bndrs, phi) = tcSplitForAllTysReq ty + tvbndrs' <- reifyTyVarBndrs req_bndrs + phi' <- reifyType phi + pure $ TH.ForallVisT tvbndrs' phi' + | otherwise + = do let (inv_bndrs, phi) = tcSplitForAllTysInvis ty + tvbndrs' <- reifyTyVarBndrs inv_bndrs + let (cxt, tau) = tcSplitPhiTy phi + cxt' <- reifyCxt cxt + tau' <- reifyType tau + pure $ TH.ForallT tvbndrs' cxt' tau' reifyTyLit :: TyCoRep.TyLit -> TcM TH.TyLit reifyTyLit (NumTyLit n) = return (TH.NumTyLit n) @@ -2177,10 +2177,6 @@ instance ReifyFlag Specificity TH.Specificity where reifyFlag SpecifiedSpec = TH.SpecifiedSpec reifyFlag InferredSpec = TH.InferredSpec -instance ReifyFlag ArgFlag TH.Specificity where - reifyFlag Required = TH.SpecifiedSpec - reifyFlag (Invisible s) = reifyFlag s - reifyTyVars :: [TyVar] -> TcM [TH.TyVarBndr ()] reifyTyVars = reifyTyVarBndrs . map mk_bndr where |