diff --git a/compiler/GHC/Builtin/Names/TH.hs b/compiler/GHC/Builtin/Names/TH.hs index 3a7d65acd0f2d5039d1d1b6f3dbbb99748f55ae0..b01a4705ec029d740b48a6f720257e21ea9651f0 100644 --- a/compiler/GHC/Builtin/Names/TH.hs +++ b/compiler/GHC/Builtin/Names/TH.hs @@ -47,6 +47,7 @@ templateHaskellNames = [ litPName, varPName, tupPName, unboxedTupPName, unboxedSumPName, conPName, tildePName, bangPName, infixPName, asPName, wildPName, recPName, listPName, sigPName, viewPName, + typePName, -- FieldPat fieldPatName, -- Match @@ -61,6 +62,7 @@ templateHaskellNames = [ fromEName, fromThenEName, fromToEName, fromThenToEName, listEName, sigEName, recConEName, recUpdEName, staticEName, unboundVarEName, labelEName, implicitParamVarEName, getFieldEName, projectionEName, + typeEName, -- FieldExp fieldExpName, -- Body @@ -268,7 +270,7 @@ charPrimLName = libFun (fsLit "charPrimL") charPrimLIdKey -- data Pat = ... litPName, varPName, tupPName, unboxedTupPName, unboxedSumPName, conPName, infixPName, tildePName, bangPName, asPName, wildPName, recPName, listPName, - sigPName, viewPName :: Name + sigPName, viewPName, typePName :: Name litPName = libFun (fsLit "litP") litPIdKey varPName = libFun (fsLit "varP") varPIdKey tupPName = libFun (fsLit "tupP") tupPIdKey @@ -284,6 +286,7 @@ recPName = libFun (fsLit "recP") recPIdKey listPName = libFun (fsLit "listP") listPIdKey sigPName = libFun (fsLit "sigP") sigPIdKey viewPName = libFun (fsLit "viewP") viewPIdKey +typePName = libFun (fsLit "typeP") typePIdKey -- type FieldPat = ... fieldPatName :: Name @@ -302,7 +305,7 @@ varEName, conEName, litEName, appEName, appTypeEName, infixEName, infixAppName, sectionLName, sectionRName, lamEName, lamCaseEName, lamCasesEName, tupEName, unboxedTupEName, unboxedSumEName, condEName, multiIfEName, letEName, caseEName, doEName, mdoEName, compEName, staticEName, unboundVarEName, - labelEName, implicitParamVarEName, getFieldEName, projectionEName :: Name + labelEName, implicitParamVarEName, getFieldEName, projectionEName, typeEName :: Name varEName = libFun (fsLit "varE") varEIdKey conEName = libFun (fsLit "conE") conEIdKey litEName = libFun (fsLit "litE") litEIdKey @@ -343,6 +346,7 @@ labelEName = libFun (fsLit "labelE") labelEIdKey implicitParamVarEName = libFun (fsLit "implicitParamVarE") implicitParamVarEIdKey getFieldEName = libFun (fsLit "getFieldE") getFieldEIdKey projectionEName = libFun (fsLit "projectionE") projectionEIdKey +typeEName = libFun (fsLit "typeE") typeEIdKey -- type FieldExp = ... fieldExpName :: Name @@ -808,7 +812,7 @@ liftStringIdKey = mkPreludeMiscIdUnique 230 -- data Pat = ... litPIdKey, varPIdKey, tupPIdKey, unboxedTupPIdKey, unboxedSumPIdKey, conPIdKey, infixPIdKey, tildePIdKey, bangPIdKey, asPIdKey, wildPIdKey, recPIdKey, - listPIdKey, sigPIdKey, viewPIdKey :: Unique + listPIdKey, sigPIdKey, viewPIdKey, typePIdKey :: Unique litPIdKey = mkPreludeMiscIdUnique 240 varPIdKey = mkPreludeMiscIdUnique 241 tupPIdKey = mkPreludeMiscIdUnique 242 @@ -824,6 +828,7 @@ recPIdKey = mkPreludeMiscIdUnique 251 listPIdKey = mkPreludeMiscIdUnique 252 sigPIdKey = mkPreludeMiscIdUnique 253 viewPIdKey = mkPreludeMiscIdUnique 254 +typePIdKey = mkPreludeMiscIdUnique 255 -- type FieldPat = ... fieldPatIdKey :: Unique @@ -846,7 +851,7 @@ varEIdKey, conEIdKey, litEIdKey, appEIdKey, appTypeEIdKey, infixEIdKey, fromEIdKey, fromThenEIdKey, fromToEIdKey, fromThenToEIdKey, listEIdKey, sigEIdKey, recConEIdKey, recUpdEIdKey, staticEIdKey, unboundVarEIdKey, labelEIdKey, implicitParamVarEIdKey, mdoEIdKey, - getFieldEIdKey, projectionEIdKey :: Unique + getFieldEIdKey, projectionEIdKey, typeEIdKey :: Unique varEIdKey = mkPreludeMiscIdUnique 270 conEIdKey = mkPreludeMiscIdUnique 271 litEIdKey = mkPreludeMiscIdUnique 272 @@ -883,28 +888,29 @@ implicitParamVarEIdKey = mkPreludeMiscIdUnique 302 mdoEIdKey = mkPreludeMiscIdUnique 303 getFieldEIdKey = mkPreludeMiscIdUnique 304 projectionEIdKey = mkPreludeMiscIdUnique 305 +typeEIdKey = mkPreludeMiscIdUnique 306 -- type FieldExp = ... fieldExpIdKey :: Unique -fieldExpIdKey = mkPreludeMiscIdUnique 306 +fieldExpIdKey = mkPreludeMiscIdUnique 307 -- data Body = ... guardedBIdKey, normalBIdKey :: Unique -guardedBIdKey = mkPreludeMiscIdUnique 307 -normalBIdKey = mkPreludeMiscIdUnique 308 +guardedBIdKey = mkPreludeMiscIdUnique 308 +normalBIdKey = mkPreludeMiscIdUnique 309 -- data Guard = ... normalGEIdKey, patGEIdKey :: Unique -normalGEIdKey = mkPreludeMiscIdUnique 309 -patGEIdKey = mkPreludeMiscIdUnique 310 +normalGEIdKey = mkPreludeMiscIdUnique 310 +patGEIdKey = mkPreludeMiscIdUnique 311 -- data Stmt = ... bindSIdKey, letSIdKey, noBindSIdKey, parSIdKey, recSIdKey :: Unique -bindSIdKey = mkPreludeMiscIdUnique 311 -letSIdKey = mkPreludeMiscIdUnique 312 -noBindSIdKey = mkPreludeMiscIdUnique 313 -parSIdKey = mkPreludeMiscIdUnique 314 -recSIdKey = mkPreludeMiscIdUnique 315 +bindSIdKey = mkPreludeMiscIdUnique 312 +letSIdKey = mkPreludeMiscIdUnique 313 +noBindSIdKey = mkPreludeMiscIdUnique 314 +parSIdKey = mkPreludeMiscIdUnique 315 +recSIdKey = mkPreludeMiscIdUnique 316 -- data Dec = ... funDIdKey, valDIdKey, dataDIdKey, newtypeDIdKey, tySynDIdKey, classDIdKey, diff --git a/compiler/GHC/Core/DataCon.hs b/compiler/GHC/Core/DataCon.hs index bb1fb96a29976764e3a0b87194f7772e05f1d99e..480f784239cc35e3b02c6e8b4c9b1154e504c148 100644 --- a/compiler/GHC/Core/DataCon.hs +++ b/compiler/GHC/Core/DataCon.hs @@ -572,12 +572,10 @@ data DataCon {- Note [TyVarBinders in DataCons] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -For the TyVarBinders in a DataCon and PatSyn: - - * Each argument flag is Inferred or Specified. - None are Required. (A DataCon is a term-level function; see - Note [No Required PiTyBinder in terms] in GHC.Core.TyCo.Rep.) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +For the TyVarBinders in a DataCon and PatSyn, +each argument flag is either Inferred or Specified, never Required. +Lifting this restriction is tracked at #18389 (DataCon) and #23704 (PatSyn). Why do we need the TyVarBinders, rather than just the TyVars? So that we can construct the right type for the DataCon with its foralls diff --git a/compiler/GHC/Core/TyCon.hs b/compiler/GHC/Core/TyCon.hs index 3aa17fe0b6aa2d25fde2296f8545099657cfd224..2afeae415599590f4d4b0f9047b644e02676dfdb 100644 --- a/compiler/GHC/Core/TyCon.hs +++ b/compiler/GHC/Core/TyCon.hs @@ -599,10 +599,11 @@ So tyConTyVarBinders converts TyCon's TyConBinders into TyVarBinders: - but changing Anon/Required to Specified The last part about Required->Specified comes from this: - data T k (a:k) b = MkT (a b) -Here k is Required in T's kind, but we don't have Required binders in -the PiTyBinders for a term (see Note [No Required PiTyBinder in terms] -in GHC.Core.TyCo.Rep), so we change it to Specified when making MkT's PiTyBinders + data T k (a :: k) b = MkT (a b) +Here k is Required in T's kind, but we didn't have Required binders in +types of terms before the advent of the new, experimental RequiredTypeArguments +extension. So we historically changed Required to Specified when making MkT's PiTyBinders +and now continue to do so to avoid a breaking change. -} diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs index 853befe5d6ff7617b11feb31e02620b24ae7c0cd..60ba6526bbb23be35d38860ed487bbb05fdf417a 100644 --- a/compiler/GHC/Driver/Session.hs +++ b/compiler/GHC/Driver/Session.hs @@ -2704,6 +2704,7 @@ xFlagsDeps = [ depFlagSpecCond "RelaxedPolyRec" LangExt.RelaxedPolyRec not "You can't turn off RelaxedPolyRec any more", + flagSpec "RequiredTypeArguments" LangExt.RequiredTypeArguments, flagSpec "RoleAnnotations" LangExt.RoleAnnotations, flagSpec "ScopedTypeVariables" LangExt.ScopedTypeVariables, flagSpec "StandaloneDeriving" LangExt.StandaloneDeriving, diff --git a/compiler/GHC/Hs/Expr.hs b/compiler/GHC/Hs/Expr.hs index 3fcb4ef1a15e6ee6db4496c8e73a6d8253d247b4..2420d6c1517e5a0abb7f15a720d0d6f06bc3d3b4 100644 --- a/compiler/GHC/Hs/Expr.hs +++ b/compiler/GHC/Hs/Expr.hs @@ -380,6 +380,12 @@ type instance XStatic GhcTc = (NameSet, Type) -- Free variables and type of expression, this is stored for convenience as wiring in -- StaticPtr is a bit tricky (see #20150) +type instance XEmbTy GhcPs = NoExtField +type instance XEmbTy GhcRn = NoExtField +type instance XEmbTy GhcTc = DataConCantHappen + -- A free-standing HsEmbTy is an error. + -- Valid usages are immediately desugared into Type. + type instance XPragE (GhcPass _) = NoExtField type instance Anno [LocatedA ((StmtLR (GhcPass pl) (GhcPass pr) (LocatedA (body (GhcPass pr)))))] = SrcSpanAnnL @@ -702,6 +708,9 @@ ppr_expr (HsProc _ pat (L _ (HsCmdTop _ cmd))) ppr_expr (HsStatic _ e) = hsep [text "static", ppr e] +ppr_expr (HsEmbTy _ _ ty) + = hsep [text "type", ppr ty] + ppr_expr (XExpr x) = case ghcPass @p of #if __GLASGOW_HASKELL__ < 811 GhcPs -> ppr x @@ -843,6 +852,7 @@ hsExprNeedsParens prec = go go (HsRecSel{}) = False go (HsProjection{}) = True go (HsGetField{}) = False + go (HsEmbTy{}) = prec > topPrec go (XExpr x) = case ghcPass @p of GhcTc -> go_x_tc x GhcRn -> go_x_rn x diff --git a/compiler/GHC/Hs/Pat.hs b/compiler/GHC/Hs/Pat.hs index 4161de9fe28a321ac2f55012003f0b6fd41086c5..304c9f56e8a70795f0ffa762b55f7070cf1ab864 100644 --- a/compiler/GHC/Hs/Pat.hs +++ b/compiler/GHC/Hs/Pat.hs @@ -155,6 +155,10 @@ type instance XSigPat GhcPs = EpAnn [AddEpAnn] type instance XSigPat GhcRn = NoExtField type instance XSigPat GhcTc = Type +type instance XEmbTyPat GhcPs = NoExtField +type instance XEmbTyPat GhcRn = NoExtField +type instance XEmbTyPat GhcTc = Type + type instance XXPat GhcPs = DataConCantHappen type instance XXPat GhcRn = HsPatExpansion (Pat GhcRn) (Pat GhcRn) -- Original pattern and its desugaring/expansion. @@ -376,6 +380,7 @@ pprPat (ConPat { pat_con = con , cpt_dicts = dicts , cpt_binds = binds } = ext +pprPat (EmbTyPat _ toktype tp) = ppr toktype <+> ppr tp pprPat (XPat ext) = case ghcPass @p of #if __GLASGOW_HASKELL__ < 811 @@ -583,6 +588,10 @@ isIrrefutableHsPat is_strict = goL -- since we cannot know until the splice is evaluated. go (SplicePat {}) = False + -- The behavior of this case is unimportant, as GHC will throw an error shortly + -- after reaching this case for other reasons (see TcRnIllegalTypePattern). + go (EmbTyPat {}) = True + go (XPat ext) = case ghcPass @p of #if __GLASGOW_HASKELL__ < 811 GhcPs -> dataConCantHappen ext @@ -651,6 +660,7 @@ isBoringHsPat = goL NPat {} -> True NPlusKPat {} -> True SplicePat {} -> False + EmbTyPat {} -> True XPat ext -> case ghcPass @p of GhcRn -> case ext of @@ -747,6 +757,7 @@ patNeedsParens p = go @p = conPatNeedsParens p ds go (SigPat {}) = p >= sigPrec go (ViewPat {}) = True + go (EmbTyPat {}) = True go (XPat ext) = case ghcPass @q of #if __GLASGOW_HASKELL__ < 901 GhcPs -> dataConCantHappen ext diff --git a/compiler/GHC/Hs/Syn/Type.hs b/compiler/GHC/Hs/Syn/Type.hs index edcdc39ea04beabd9474693b24daf70b587ec654..0b45ff88fd0eb1a461c238a05fcb0a055ab05eea 100644 --- a/compiler/GHC/Hs/Syn/Type.hs +++ b/compiler/GHC/Hs/Syn/Type.hs @@ -63,6 +63,7 @@ hsPatType (ConPat { pat_con = lcon hsPatType (SigPat ty _ _) = ty hsPatType (NPat ty _ _ _) = ty hsPatType (NPlusKPat ty _ _ _ _ _) = ty +hsPatType (EmbTyPat ty _ _) = typeKind ty hsPatType (XPat ext) = case ext of CoPat _ _ ty -> ty @@ -142,6 +143,7 @@ hsExprType (HsUntypedSplice ext _) = dataConCantHappen ext hsExprType (HsProc _ _ lcmd_top) = lhsCmdTopType lcmd_top hsExprType (HsStatic (_, ty) _s) = ty hsExprType (HsPragE _ _ e) = lhsExprType e +hsExprType (HsEmbTy x _ _) = dataConCantHappen x hsExprType (XExpr (WrapExpr (HsWrap wrap e))) = hsWrapperType wrap $ hsExprType e hsExprType (XExpr (ExpansionExpr (HsExpanded _ tc_e))) = hsExprType tc_e hsExprType (XExpr (ConLikeTc con _ _)) = conLikeType con diff --git a/compiler/GHC/Hs/Utils.hs b/compiler/GHC/Hs/Utils.hs index afa7821031761eb942dc714f0d5440454b6a6ce1..7f9883432e19253e2f967e009f026cd5760b6ddf 100644 --- a/compiler/GHC/Hs/Utils.hs +++ b/compiler/GHC/Hs/Utils.hs @@ -1233,11 +1233,15 @@ collect_pat flag pat bndrs = case pat of NPat {} -> bndrs NPlusKPat _ n _ _ _ _ -> unXRec @p n : bndrs SigPat _ pat sig -> case flag of - CollVarTyVarBinders -> collect_lpat flag pat bndrs - ++ collectPatSigBndrs sig - _ -> collect_lpat flag pat bndrs + CollNoDictBinders -> collect_lpat flag pat bndrs + CollWithDictBinders -> collect_lpat flag pat bndrs + CollVarTyVarBinders -> collect_lpat flag pat bndrs ++ collectPatSigBndrs sig XPat ext -> collectXXPat @p flag ext bndrs SplicePat ext _ -> collectXSplicePat @p flag ext bndrs + EmbTyPat _ _ tp -> case flag of + CollNoDictBinders -> bndrs + CollWithDictBinders -> bndrs + CollVarTyVarBinders -> collectTyPatBndrs tp ++ bndrs -- See Note [Dictionary binders in ConPatOut] ConPat {pat_args=ps} -> case flag of CollNoDictBinders -> foldr (collect_lpat flag) bndrs (hsConPatArgs ps) diff --git a/compiler/GHC/HsToCore/Expr.hs b/compiler/GHC/HsToCore/Expr.hs index 29fc3a5713c356a695c7e444f8f4697923e8499a..59970138dd1b27d194350cb5efaf384ec8878257 100644 --- a/compiler/GHC/HsToCore/Expr.hs +++ b/compiler/GHC/HsToCore/Expr.hs @@ -365,6 +365,8 @@ dsExpr (ExplicitSum types alt arity expr) dsExpr (HsPragE _ prag expr) = ds_prag_expr prag expr +dsExpr (HsEmbTy x _ _) = dataConCantHappen x + dsExpr (HsCase ctxt discrim matches) = do { core_discrim <- dsLExpr discrim ; ([discrim_var], matching_code) <- matchWrapper ctxt (Just [discrim]) matches diff --git a/compiler/GHC/HsToCore/Match.hs b/compiler/GHC/HsToCore/Match.hs index 54f9741f01b617d17d25fc0705b8e0e15e7fc9b0..5914371dc97263bb935af4050888087f2470521b 100644 --- a/compiler/GHC/HsToCore/Match.hs +++ b/compiler/GHC/HsToCore/Match.hs @@ -1265,6 +1265,7 @@ patGroup _ (NPlusKPat _ _ (L _ (OverLit {ol_val=oval})) _ _ _) = _ -> pprPanic "patGroup NPlusKPat" (ppr oval) patGroup _ (ViewPat _ expr p) = PgView expr (hsPatType (unLoc p)) patGroup platform (LitPat _ lit) = PgLit (hsLitKey platform lit) +patGroup _ EmbTyPat{} = PgAny patGroup platform (XPat ext) = case ext of CoPat _ p _ -> PgCo (hsPatType p) -- Type of innelexp pattern ExpansionPat _ p -> patGroup platform p diff --git a/compiler/GHC/HsToCore/Pmc/Desugar.hs b/compiler/GHC/HsToCore/Pmc/Desugar.hs index 118feb87af9f8ed60ba58e187416803d7af8766d..0382ee61d6a03e5177182baeeda36db8c6b149b3 100644 --- a/compiler/GHC/HsToCore/Pmc/Desugar.hs +++ b/compiler/GHC/HsToCore/Pmc/Desugar.hs @@ -123,6 +123,7 @@ desugarPat x pat = case pat of AsPat _ (L _ y) _ p -> (mkPmLetVar y x ++) <$> desugarLPat y p SigPat _ p _ty -> desugarLPat x p + EmbTyPat _ _ _ -> pure [] XPat ext -> case ext of diff --git a/compiler/GHC/HsToCore/Quote.hs b/compiler/GHC/HsToCore/Quote.hs index 69db68f8652b034e103f59040511f3c622fcbedf..0e37c632ecb8ae62cd21f69f09605bf154ed73e7 100644 --- a/compiler/GHC/HsToCore/Quote.hs +++ b/compiler/GHC/HsToCore/Quote.hs @@ -1666,6 +1666,9 @@ repE (HsGetField _ e (L _ (DotFieldOcc _ (L _ (FieldLabelString f))))) = do e1 <- repLE e repGetField e1 f repE (HsProjection _ xs) = repProjection (fmap (field_label . unLoc . dfoLabel . unLoc) xs) +repE (HsEmbTy _ _ t) = do + t1 <- repLTy (hswc_body t) + rep2 typeEName [unC t1] repE (XExpr (HsExpanded orig_expr ds_expr)) = do { rebindable_on <- lift $ xoptM LangExt.RebindableSyntax ; if rebindable_on -- See Note [Quotation and rebindable syntax] @@ -2123,6 +2126,8 @@ repP p@(NPat _ (L _ l) (Just _) _) repP (SigPat _ p t) = do { p' <- repLP p ; t' <- repLTy (hsPatSigType t) ; repPsig p' t' } +repP (EmbTyPat _ _ t) = do { t' <- repLTy (hstp_body t) + ; repPtype t' } repP (SplicePat (HsUntypedSpliceNested n) _) = rep_splice n repP p@(SplicePat (HsUntypedSpliceTop _ _) _) = pprPanic "repP: top level splice" (ppr p) repP other = notHandled (ThExoticPattern other) @@ -2379,6 +2384,9 @@ repPview (MkC e) (MkC p) = rep2 viewPName [e,p] repPsig :: Core (M TH.Pat) -> Core (M TH.Type) -> MetaM (Core (M TH.Pat)) repPsig (MkC p) (MkC t) = rep2 sigPName [p, t] +repPtype :: Core (M TH.Type) -> MetaM (Core (M TH.Pat)) +repPtype (MkC t) = rep2 typePName [t] + --------------- Expressions ----------------- repVarOrCon :: Name -> Core TH.Name -> MetaM (Core (M TH.Exp)) repVarOrCon vc str diff --git a/compiler/GHC/HsToCore/Ticks.hs b/compiler/GHC/HsToCore/Ticks.hs index c3b50537855f78c2c562f7c86ac3062644ae225a..cf6fbac0677ebc82cc3d68e0cbb768f5d36c9dfb 100644 --- a/compiler/GHC/HsToCore/Ticks.hs +++ b/compiler/GHC/HsToCore/Ticks.hs @@ -478,6 +478,7 @@ addTickHsExpr e@(HsIPVar {}) = return e addTickHsExpr e@(HsOverLit {}) = return e addTickHsExpr e@(HsOverLabel{}) = return e addTickHsExpr e@(HsLit {}) = return e +addTickHsExpr e@(HsEmbTy {}) = return e addTickHsExpr (HsLam x mg) = liftM (HsLam x) (addTickMatchGroup True mg) addTickHsExpr (HsLamCase x lc_variant mgs) = liftM (HsLamCase x lc_variant) diff --git a/compiler/GHC/Iface/Ext/Ast.hs b/compiler/GHC/Iface/Ext/Ast.hs index a2578641ca909c395eb886cc247dfe1579c68a7e..26d3578b0fb669617d0f57dab91836e03d32e06e 100644 --- a/compiler/GHC/Iface/Ext/Ast.hs +++ b/compiler/GHC/Iface/Ext/Ast.hs @@ -1027,6 +1027,9 @@ instance HiePass p => ToHie (PScoped (LocatedA (Pat (GhcPass p)))) where sig HieRn -> pure [] ] + EmbTyPat _ _ tp -> + [ toHie $ TS (ResolvedScopes [scope, pscope]) tp + ] XPat e -> case hiePass @p of HieRn -> case e of @@ -1199,6 +1202,9 @@ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where HsStatic _ expr -> [ toHie expr ] + HsEmbTy _ _ ty -> + [ toHie $ TS (ResolvedScopes []) ty + ] HsTypedBracket xbracket b -> case hiePass @p of HieRn -> [ toHie b diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y index 6af984715868e747f672551c86c758743e34b7ee..3b089726b680caeb635cfcd5ba031e0d2676ce84 100644 --- a/compiler/GHC/Parser.y +++ b/compiler/GHC/Parser.y @@ -2738,6 +2738,11 @@ exp :: { ECP } | infixexp %shift { $1 } | exp_prag(exp) { $1 } -- See Note [Pragmas and operator fixity] + -- Embed types into expressions and patterns for required type arguments + | 'type' atype + {% do { requireExplicitNamespaces (getLoc $1) + ; return $ ECP $ mkHsEmbTyPV (comb2 $1 (reLoc $>)) (hsTok $1) $2 } } + infixexp :: { ECP } : exp10 { $1 } | infixexp qop exp10p -- See Note [Pragmas and operator fixity] diff --git a/compiler/GHC/Parser/PostProcess.hs b/compiler/GHC/Parser/PostProcess.hs index caa0c35f0d8fb3abd15a900e36f1feab12760784..ea8f19053a1c3194e94cc97c6178f565d6f73eaf 100644 --- a/compiler/GHC/Parser/PostProcess.hs +++ b/compiler/GHC/Parser/PostProcess.hs @@ -96,6 +96,7 @@ module GHC.Parser.PostProcess ( failOpFewArgs, failNotEnabledImportQualifiedPost, failImportQualifiedTwice, + requireExplicitNamespaces, SumOrTuple (..), @@ -1643,6 +1644,8 @@ class (b ~ (Body b) GhcPs, AnnoBody b) => DisambECP b where -- | Disambiguate tuple sections and unboxed sums mkSumOrTuplePV :: SrcSpanAnnA -> Boxity -> SumOrTuple b -> [AddEpAnn] -> PV (LocatedA b) + -- | Disambiguate "type t" (embedded type) + mkHsEmbTyPV :: SrcSpan -> LHsToken "type" GhcPs -> LHsType GhcPs -> PV (LocatedA b) -- | Validate infixexp LHS to reject unwanted {-# SCC ... #-} pragmas rejectPragmaPV :: LocatedA b -> PV () @@ -1762,6 +1765,7 @@ instance DisambECP (HsCmd GhcPs) where mkHsBangPatPV l c _ = cmdFail l $ text "!" <> ppr c mkSumOrTuplePV l boxity a _ = cmdFail (locA l) (pprSumOrTuple boxity a) + mkHsEmbTyPV l _ ty = cmdFail l (text "type" <+> ppr ty) rejectPragmaPV _ = return () cmdFail :: SrcSpan -> SDoc -> PV a @@ -1858,6 +1862,9 @@ instance DisambECP (HsExpr GhcPs) where mkHsBangPatPV l e _ = addError (mkPlainErrorMsgEnvelope l $ PsErrBangPatWithoutSpace e) >> return (L (noAnnSrcSpan l) (hsHoleExpr noAnn)) mkSumOrTuplePV = mkSumOrTupleExpr + mkHsEmbTyPV l toktype ty = + return $ L (noAnnSrcSpan l) $ + HsEmbTy noExtField toktype (mkHsWildCardBndrs ty) rejectPragmaPV (L _ (OpApp _ _ _ e)) = -- assuming left-associative parsing of operators rejectPragmaPV e @@ -1943,6 +1950,9 @@ instance DisambECP (PatBuilder GhcPs) where hintBangPat l pb return $ L (noAnnSrcSpan l) (PatBuilderPat pb) mkSumOrTuplePV = mkSumOrTuplePat + mkHsEmbTyPV l toktype ty = + return $ L (noAnnSrcSpan l) $ + PatBuilderPat (EmbTyPat noExtField toktype (mkHsTyPat noAnn ty)) rejectPragmaPV _ = return () -- | Ensure that a literal pattern isn't of type Addr#, Float#, Double#. @@ -2894,9 +2904,7 @@ mkModuleImpExp warning anns (L l specname) subs = do mkTypeImpExp :: LocatedN RdrName -- TcCls or Var name space -> P (LocatedN RdrName) mkTypeImpExp name = - do allowed <- getBit ExplicitNamespacesBit - unless allowed $ addError $ mkPlainErrorMsgEnvelope (getLocA name) $ - PsErrIllegalExplicitNamespace + do requireExplicitNamespaces (getLocA name) return (fmap (`setRdrNameSpace` tcClsName) name) checkImportSpec :: LocatedL [LIE GhcPs] -> P (LocatedL [LIE GhcPs]) @@ -2947,6 +2955,12 @@ failOpFewArgs (L loc op) = ; addFatalError $ mkPlainErrorMsgEnvelope (locA loc) $ (PsErrOpFewArgs is_star_type op) } +requireExplicitNamespaces :: MonadP m => SrcSpan -> m () +requireExplicitNamespaces l = do + allowed <- getBit ExplicitNamespacesBit + unless allowed $ + addError $ mkPlainErrorMsgEnvelope l PsErrIllegalExplicitNamespace + ----------------------------------------------------------------------------- -- Misc utils diff --git a/compiler/GHC/Rename/Bind.hs b/compiler/GHC/Rename/Bind.hs index 9d415328123a485cdaa4c930386a4cb269313dd2..bf0cc6abc65ae9384f42c6fd3eb7249927b1bd06 100644 --- a/compiler/GHC/Rename/Bind.hs +++ b/compiler/GHC/Rename/Bind.hs @@ -581,6 +581,10 @@ isOkNoBindPattern (L _ pat) = ConPat _ _ cpd -> any lpatternContainsSplice (hsConPatArgs cpd) XPat (HsPatExpanded _orig new) -> patternContainsSplice new + -- The behavior of this case is unimportant, as GHC will throw an error shortly + -- after reaching this case for other reasons (see TcRnIllegalTypePattern). + EmbTyPat{} -> True + {- Note [Pattern bindings that bind no variables] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Generally, we want to warn about pattern bindings like diff --git a/compiler/GHC/Rename/Expr.hs b/compiler/GHC/Rename/Expr.hs index 2965d290126ea77bb15f55264a278c35cf96e97d..03dd39f00eee7e6b73930fff09a8bc358ab36414 100644 --- a/compiler/GHC/Rename/Expr.hs +++ b/compiler/GHC/Rename/Expr.hs @@ -564,6 +564,10 @@ rnExpr (ArithSeq _ _ seq) else return (ArithSeq noExtField Nothing new_seq, fvs) } +rnExpr (HsEmbTy _ toktype ty) + = do { (ty', fvs) <- rnHsWcType HsTypeCtx ty + ; return (HsEmbTy noExtField toktype ty', fvs) } + {- ************************************************************************ * * @@ -2301,6 +2305,11 @@ isStrictPattern (L loc pat) = NPat{} -> True NPlusKPat{} -> True SplicePat{} -> True + + -- The behavior of this case is unimportant, as GHC will throw an error shortly + -- after reaching this case for other reasons (see TcRnIllegalTypePattern). + EmbTyPat{} -> False + XPat ext -> case ghcPass @p of #if __GLASGOW_HASKELL__ < 811 GhcPs -> dataConCantHappen ext diff --git a/compiler/GHC/Rename/Pat.hs b/compiler/GHC/Rename/Pat.hs index 59e596a37934079cca860d3dfc3c38bc942d1b41..7412f0bfd536081483b7b71f9d064eb7dadebefc 100644 --- a/compiler/GHC/Rename/Pat.hs +++ b/compiler/GHC/Rename/Pat.hs @@ -633,6 +633,10 @@ rnPatAndThen mk (SplicePat _ splice) (rn_splice, HsUntypedSpliceNested splice_name) -> return (SplicePat (HsUntypedSpliceNested splice_name) rn_splice) -- Splice was nested and thus already renamed } +rnPatAndThen _ (EmbTyPat _ toktype tp) + = do { tp' <- rnHsTyPat HsTypePatCtx tp + ; return (EmbTyPat noExtField toktype tp') } + -------------------- rnConPatAndThen :: NameMaker -> LocatedN RdrName -- the constructor diff --git a/compiler/GHC/Tc/Errors/Ppr.hs b/compiler/GHC/Tc/Errors/Ppr.hs index 27ca34f9fc0c617f7ab485b88344a5947c37e7b7..a698af9dff4b8ea8bf202e3f4fcba2d9bac5a982 100644 --- a/compiler/GHC/Tc/Errors/Ppr.hs +++ b/compiler/GHC/Tc/Errors/Ppr.hs @@ -435,11 +435,10 @@ instance Diagnostic TcRnMessage where TcRnIllegalInstance reason -> mkSimpleDecorated $ pprIllegalInstance reason TcRnVDQInTermType mb_ty - -> mkSimpleDecorated $ vcat - [ case mb_ty of + -> mkSimpleDecorated $ + case mb_ty of Nothing -> main_msg Just ty -> hang (main_msg <> char ':') 2 (pprType ty) - , text "(GHC does not yet support this)" ] where main_msg = text "Illegal visible, dependent quantification" <+> @@ -1231,6 +1230,25 @@ instance Diagnostic TcRnMessage where hang (text "Missing role annotation" <> colon) 2 (text "type role" <+> ppr name <+> hsep (map ppr roles)) + TcRnIllformedTypePattern p + -> mkSimpleDecorated $ + hang (text "Ill-formed type pattern:") 2 (ppr p) $$ + text "Expected a type pattern introduced with the" + <+> quotes (text "type") <+> text "keyword." + TcRnIllegalTypePattern + -> mkSimpleDecorated $ + text "Illegal type pattern." $$ + text "A type pattern must be checked against a visible forall." + TcRnIllformedTypeArgument e + -> mkSimpleDecorated $ + hang (text "Ill-formed type argument:") 2 (ppr e) $$ + text "Expected a type expression introduced with the" + <+> quotes (text "type") <+> text "keyword." + TcRnIllegalTypeExpr + -> mkSimpleDecorated $ + text "Illegal type expression." $$ + text "A type expression must be used to instantiate a visible forall." + TcRnCapturedTermName tv_name shadowed_term_names -> mkSimpleDecorated $ text "The type variable" <+> quotes (ppr tv_name) <+> @@ -2418,6 +2436,14 @@ instance Diagnostic TcRnMessage where -> WarningWithFlag Opt_WarnImplicitRhsQuantification TcRnPatersonCondFailure{} -> ErrorWithoutFlag + TcRnIllformedTypePattern{} + -> ErrorWithoutFlag + TcRnIllegalTypePattern{} + -> ErrorWithoutFlag + TcRnIllformedTypeArgument{} + -> ErrorWithoutFlag + TcRnIllegalTypeExpr{} + -> ErrorWithoutFlag diagnosticHints = \case TcRnUnknownMessage m @@ -2537,8 +2563,9 @@ instance Diagnostic TcRnMessage where -> noHints TcRnForAllEscapeError{} -> noHints - TcRnVDQInTermType{} - -> noHints + TcRnVDQInTermType mb_ty + | isJust mb_ty -> [suggestExtension LangExt.RequiredTypeArguments] + | otherwise -> [] TcRnBadQuantPredHead{} -> noHints TcRnIllegalTupleConstraint{} @@ -3061,6 +3088,14 @@ instance Diagnostic TcRnMessage where -> [SuggestBindTyVarOnLhs (unLoc kv)] TcRnPatersonCondFailure{} -> [suggestExtension LangExt.UndecidableInstances] + TcRnIllformedTypePattern{} + -> noHints + TcRnIllegalTypePattern{} + -> noHints + TcRnIllformedTypeArgument{} + -> noHints + TcRnIllegalTypeExpr{} + -> noHints diagnosticCode :: TcRnMessage -> Maybe DiagnosticCode diagnosticCode = constructorCode diff --git a/compiler/GHC/Tc/Errors/Types.hs b/compiler/GHC/Tc/Errors/Types.hs index 8b566a095b6e4bf05d6e95b2d08809abbd65a78b..2d9e197d69f631df0bca8e2c51f680d76b361558 100644 --- a/compiler/GHC/Tc/Errors/Types.hs +++ b/compiler/GHC/Tc/Errors/Types.hs @@ -4027,6 +4027,77 @@ data TcRnMessage where -} TcRnImplicitRhsQuantification :: LocatedN RdrName -> TcRnMessage + {-| TcRnIllformedTypePattern is an error raised when the pattern + corresponding to a required type argument (visible forall) + does not have a form that can be interpreted as a type pattern. + + At the moment, only patterns constructed using the @type@ keyword + are considered well-formed, but this restriction will be relaxed + when part 2 of GHC Proposal #281 is implemented. + + Example: + + vfun :: forall (a :: k) -> () + vfun x = () + -- ^ + -- expected `type x` instead of `x` + + Test cases: + T22326_fail_raw_pat + -} + TcRnIllformedTypePattern :: !(Pat GhcRn) -> TcRnMessage + + {-| TcRnIllegalTypePattern is an error raised when a pattern constructed + with the @type@ keyword occurs in a position that does not correspond + to a required type argument (visible forall). + + Example: + + case x of + (type _) -> True -- the (type _) pattern is illegal here + _ -> False + + Test cases: + T22326_fail_ado + T22326_fail_caseof + -} + TcRnIllegalTypePattern :: TcRnMessage + + {-| TcRnIllformedTypeArgument is an error raised when an argument + that specifies a required type argument (instantiates a visible forall) + does not have a form that can be interpreted as a type argument. + + At the moment, only expressions constructed using the @type@ keyword + are considered well-formed, but this restriction will be relaxed + when part 2 of GHC Proposal #281 is implemented. + + Example: + + vfun :: forall (a :: k) -> () + x = vfun Int + -- ^^^ + -- expected `type Int` instead of `Int` + + Test cases: + T22326_fail_raw_arg + -} + TcRnIllformedTypeArgument :: !(LHsExpr GhcRn) -> TcRnMessage + + {-| TcRnIllegalTypeExpr is an error raised when an expression constructed + with the @type@ keyword occurs in a position that does not correspond + to a required type argument (visible forall). + + Example: + + xtop = type Int -- not a function argument + xarg = length (type Int) -- `length` does not expect a required type argument + + Test cases: + T22326_fail_app + T22326_fail_top + -} + TcRnIllegalTypeExpr :: TcRnMessage + deriving Generic diff --git a/compiler/GHC/Tc/Gen/App.hs b/compiler/GHC/Tc/Gen/App.hs index 7d1a7cbbffbf512c5a8871c9becb2b916cd1e588..317d1b856ecbb94bc759285e68236a7d6d60a65f 100644 --- a/compiler/GHC/Tc/Gen/App.hs +++ b/compiler/GHC/Tc/Gen/App.hs @@ -597,6 +597,11 @@ tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args -- go1: fun_ty is not filled-in instantiation variable -- ('go' dealt with that case) + -- Handle out-of-scope functions gracefully + go1 delta acc so_far fun_ty (arg : rest_args) + | fun_is_out_of_scope, looks_like_type_arg arg -- See Note [VTA for out-of-scope functions] + = go delta acc so_far fun_ty rest_args + -- Rule IALL from Fig 4 of the QL paper -- c.f. GHC.Tc.Utils.Instantiate.topInstantiate go1 delta acc so_far fun_ty args @@ -630,6 +635,14 @@ tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args -- Going around again means we deal easily with -- nested forall a. Eq a => forall b. Show b => blah + -- Rule ITVDQ from the GHC Proposal #281 + go1 delta acc so_far fun_ty ((EValArg { eva_arg = ValArg arg }) : rest_args) + | Just (tvb, body) <- tcSplitForAllTyVarBinder_maybe fun_ty + , binderFlag tvb == Required + = do { (ty_arg, inst_body) <- tcVDQ fun_conc_tvs (tvb, body) arg + ; let wrap = mkWpTyApps [ty_arg] + ; go delta (addArgWrap wrap acc) so_far inst_body rest_args } + -- Rule IRESULT from Fig 4 of the QL paper go1 delta acc _ fun_ty [] = do { traceTc "tcInstFun:ret" (ppr fun_ty) @@ -644,10 +657,6 @@ tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args -- Rule ITYARG from Fig 4 of the QL paper go1 delta acc so_far fun_ty ( ETypeArg { eva_ctxt = ctxt, eva_at = at, eva_hs_ty = hs_ty } : rest_args ) - | fun_is_out_of_scope -- See Note [VTA for out-of-scope functions] - = go delta acc so_far fun_ty rest_args - - | otherwise = do { (ty_arg, inst_ty) <- tcVTA fun_conc_tvs fun_ty hs_ty ; let arg' = ETypeArg { eva_ctxt = ctxt, eva_at = at, eva_hs_ty = hs_ty, eva_ty = ty_arg } ; go delta (arg' : acc) so_far inst_ty rest_args } @@ -727,6 +736,31 @@ tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args : addArgWrap wrap acc ; go delta' acc' (arg_ty:so_far) res_ty rest_args } +-- Is the argument supposed to instantiate a forall? +-- +-- In other words, given a function application `fn arg`, +-- can we look at the `arg` and conclude that `fn :: forall x. t` +-- or `fn :: forall x -> t`? +-- +-- This is a conservative heuristic that returns `False` for "don't know". +-- Used to improve error messages only. +-- See Note [VTA for out-of-scope functions]. +looks_like_type_arg :: HsExprArg 'TcpRn -> Bool +looks_like_type_arg ETypeArg{} = + -- The argument is clearly supposed to instantiate an invisible forall, + -- i.e. when we see `f @a`, we expect `f :: forall x. t`. + True +looks_like_type_arg EValArg{ eva_arg = ValArg (L _ e) } = + -- Check if the argument is supposed to instantiate a visible forall, + -- i.e. when we see `f (type Int)`, we expect `f :: forall x -> t`, + -- but not if we see `f True`. + -- We can't say for sure though. Part 2 of GHC Proposal #281 allows + -- type arguments without the `type` qualifier, so `f True` could + -- instantiate `forall (b :: Bool) -> t`. + case stripParensHsExpr e of + HsEmbTy _ _ _ -> True + _ -> False +looks_like_type_arg _ = False addArgCtxt :: AppCtxt -> LHsExpr GhcRn -> TcM a -> TcM a @@ -757,6 +791,7 @@ addArgCtxt ctxt (L arg_loc arg) thing_inside * * ********************************************************************* -} +-- See Note [Visible type application and abstraction] tcVTA :: ConcreteTyVars -- ^ Type variables that must be instantiated to concrete types. -- @@ -770,9 +805,28 @@ tcVTA :: ConcreteTyVars tcVTA conc_tvs fun_ty hs_ty | Just (tvb, inner_ty) <- tcSplitForAllTyVarBinder_maybe fun_ty , binderFlag tvb == Specified - -- It really can't be Inferred, because we've just - -- instantiated those. But, oddly, it might just be Required. - -- See Note [Required quantifiers in the type of a term] + = do { tc_inst_forall_arg conc_tvs (tvb, inner_ty) hs_ty } + + | otherwise + = do { (_, fun_ty) <- liftZonkM $ zonkTidyTcType emptyTidyEnv fun_ty + ; failWith $ TcRnInvalidTypeApplication fun_ty hs_ty } + +-- See Note [Visible type application and abstraction] +tcVDQ :: ConcreteTyVars -- See Note [Representation-polymorphism checking built-ins] + -> (ForAllTyBinder, TcType) -- Function type + -> LHsExpr GhcRn -- Argument type + -> TcM (TcType, TcType) +tcVDQ conc_tvs (tvb, inner_ty) arg + = do { hs_ty <- case stripParensLHsExpr arg of + L _ (HsEmbTy _ _ hs_ty) -> return hs_ty + e -> failWith $ TcRnIllformedTypeArgument e + ; tc_inst_forall_arg conc_tvs (tvb, inner_ty) hs_ty } + +tc_inst_forall_arg :: ConcreteTyVars -- See Note [Representation-polymorphism checking built-ins] + -> (ForAllTyBinder, TcType) -- Function type + -> LHsWcType GhcRn -- Argument type + -> TcM (TcType, TcType) +tc_inst_forall_arg conc_tvs (tvb, inner_ty) hs_ty = do { let tv = binderVar tvb kind = tyVarKind tv tv_nm = tyVarName tv @@ -805,40 +859,260 @@ tcVTA conc_tvs fun_ty hs_ty ; inner_ty <- liftZonkM $ zonkTcType inner_ty -- See Note [Visible type application zonk] - ; let in_scope = mkInScopeSet (tyCoVarsOfTypes [fun_ty, ty_arg]) + ; let fun_ty = mkForAllTy tvb inner_ty + in_scope = mkInScopeSet (tyCoVarsOfTypes [fun_ty, ty_arg]) insted_ty = substTyWithInScope in_scope [tv] [ty_arg] inner_ty -- NB: tv and ty_arg have the same kind, so this -- substitution is kind-respecting - ; traceTc "VTA" (vcat [ text "fun_ty" <+> ppr fun_ty - , text "tv" <+> ppr tv <+> dcolon <+> debugPprType kind - , text "ty_arg" <+> debugPprType ty_arg <+> dcolon - <+> debugPprType (typeKind ty_arg) - , text "inner_ty" <+> debugPprType inner_ty - , text "insted_ty" <+> debugPprType insted_ty ]) - ; return (ty_arg, insted_ty) } - - | otherwise - = do { (_, fun_ty) <- liftZonkM $ zonkTidyTcType emptyTidyEnv fun_ty - ; failWith $ TcRnInvalidTypeApplication fun_ty hs_ty } - -{- Note [Required quantifiers in the type of a term] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Consider (#15859) - - data A k :: k -> Type -- A :: forall k -> k -> Type - type KindOf (a :: k) = k -- KindOf :: forall k. k -> Type - a = (undefined :: KindOf A) @Int -With ImpredicativeTypes (thin ice, I know), we instantiate -KindOf at type (forall k -> k -> Type), so - KindOf A = forall k -> k -> Type -whose first argument is Required - -We want to reject this type application to Int, but in earlier -GHCs we had an ASSERT that Required could not occur here. + ; traceTc "tc_inst_forall_arg (VTA/VDQ)" ( + vcat [ text "fun_ty" <+> ppr fun_ty + , text "tv" <+> ppr tv <+> dcolon <+> debugPprType kind + , text "ty_arg" <+> debugPprType ty_arg <+> dcolon + <+> debugPprType (typeKind ty_arg) + , text "inner_ty" <+> debugPprType inner_ty + , text "insted_ty" <+> debugPprType insted_ty ]) + ; return (ty_arg, insted_ty) } -The ice is thin; c.f. Note [No Required PiTyBinder in terms] -in GHC.Core.TyCo.Rep. +{- Note [Visible type application and abstraction] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GHC supports the types + forall {a}. a -> t -- ForAllTyFlag is Inferred + forall a. a -> t -- ForAllTyFlag is Specified + forall a -> a -> t -- ForAllTyFlag is Required + +The design of type abstraction and type application for those types has gradually +evolved over time, and is based on the following papers and proposals: + - "Visible Type Application" + https://richarde.dev/papers/2016/type-app/visible-type-app.pdf + - "Type Variables in Patterns" + https://richarde.dev/papers/2018/pat-tyvars/pat-tyvars.pdf + - "Modern Scoped Type Variables" + https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0448-type-variable-scoping.rst + - "Visible forall in types of terms" + https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0281-visible-forall.rst + +Here we offer an overview of the design mixed with commentary on the +implementation status. The proposals have not been fully implemented at the +time of writing this Note (see "not implemented" in the rest of this Note). + +Now consider functions + fi :: forall {a}. a -> t -- Inferred: type argument cannot be supplied + fs :: forall a. a -> t -- Specified: type argument may be supplied + fr :: forall a -> a -> t -- Required: type argument must be supplied + +At a call site we may have calls looking like this + fi True -- Inferred: no visible type argument + fs True -- Specified: type argument omitted + fs @Bool True -- Specified: type argument supplied + fr (type Bool) True -- Required: type argument is compulsory, `type` qualifier used + fr Bool True -- Required: type argument is compulsory, `type` qualifier omitted (NB: not implemented) + +At definition sites we may have type /patterns/ to abstract over type variables + fi x = rhs -- Inferred: no type pattern + fs x = rhs -- Specified: type pattern omitted + fs @a (x :: a) = rhs -- Specified: type pattern supplied (NB: not implemented) + fr (type a) (x :: a) = rhs -- Required: type pattern is compulsory, `type` qualifier used + fr a (x :: a) = rhs -- Required: type pattern is compulsory, `type` qualifier omitted (NB: not implemented) + +Type patterns in lambdas work the same way as they do in a function LHS + fs = \ x -> rhs -- Specified: type pattern omitted + fs = \ @a (x :: a) -> rhs -- Specified: type pattern supplied (NB: not implemented) + fr = \ (type a) (x :: a) -> rhs -- Required: type pattern is compulsory, `type` qualifier used + fr = \ a (x :: a) -> rhs -- Required: type pattern is compulsory, `type` qualifier omitted (NB: not implemented) + +Type patterns may also occur in a constructor pattern. Consider the following data declaration + data T where + MkTI :: forall {a}. Show a => a -> T -- Inferred + MkTS :: forall a. Show a => a -> T -- Specified + MkTR :: forall a -> Show a => a -> T -- Required (NB: not implemented) + +Matching on its constructors may look like this + f (MkTI x) = rhs -- Inferred: no type pattern + f (MkTS x) = rhs -- Specified: type pattern omitted + f (MkTS @a (x :: a)) = rhs -- Specified: type pattern supplied + f (MkTR (type a) (x :: a)) = rhs -- Required: type pattern is compulsory, `type` qualifier used (NB: not implemented) + f (MkTR a (x :: a)) = rhs -- Required: type pattern is compulsory, `type` qualifier omitted (NB: not implemented) + +The moving parts are as follows: + (abbreviations used: "c.o." = "constructor of") + +Syntax of types +--------------- +* The types are all initially represented with HsForAllTy (c.o. HsType). + The binders are in the (hst_tele :: HsForAllTelescope pass) field of the HsForAllTy + At this stage, we have + forall {a}. t -- HsForAllInvis (c.o. HsForAllTelescope) and InferredSpec (c.o. Specificity) + forall a. t -- HsForAllInvis (c.o. HsForAllTelescope) and SpecifiedSpec (c.o. Specificity) + forall a -> t -- HsForAllVis (c.o. HsForAllTelescope) + +* By the time we get to checking applications/abstractions (e.g. GHC.Tc.Gen.App) + the types have been kind-checked (e.g. by tcLHsType) into ForAllTy (c.o. Type). + At this stage, we have: + forall {a}. t -- ForAllTy (c.o. Type) and Inferred (c.o. ForAllTyFlag) + forall a. t -- ForAllTy (c.o. Type) and Specified (c.o. ForAllTyFlag) + forall a -> t -- ForAllTy (c.o. Type) and Required (c.o. ForAllTyFlag) + +Syntax of applications in HsExpr +-------------------------------- +* We represent type applications in HsExpr like this (ignoring parameterisation) + data HsExpr = HsApp HsExpr HsExpr -- (f True) (plain function application) + | HsAppType HsExpr HsType -- (f @True) (function application with `@`) + | HsEmbTy HsType -- (type Int) (embed a type into an expression with `type`) + | ... + +* So (f @ty) is represented, just as you might expect: + HsAppType f ty + +* But (f (type ty)) is represented by: + HsApp f (HsEmbTy ty) + + Why the difference? Because we /also/ need to express these /nested/ uses of `type`: + + g (Maybe (type Int)) -- valid for g :: forall (a :: Type) -> t (NB. not implemented) + g (Either (type Int) (type Bool)) -- valid for g :: forall (a :: Type) -> t (NB. not implemented) + + This nesting makes `type` rather different from `@`. Remember, the HsEmbTy mainly just + switches namespace, and is subject to the term-to-type transformation. + +Syntax of abstractions in Pat +----------------------------- +* Type patterns are represented in Pat roughly like this + data Pat = ConPat ConLike [HsTyPat] [Pat] -- (Con @tp1 @tp2 p1 p2) (constructor pattern) + | EmbTyPat HsTyPat -- (type tp) (embed a type into a pattern with `type`) + | ... + data HsTyPat = HsTP LHsType + (In ConPat, the type and term arguments are actually inside HsConPatDetails.) + + * Similar to HsAppType in HsExpr, the [HsTyPat] in ConPat is used just for @ty arguments + * Similar to HsEmbTy in HsExpr, EmbTyPat lets you embed a type in a pattern + +* Examples: + \ (MkT @a (x :: a)) -> rhs -- ConPat (c.o. Pat) and HsConPatTyArg (c.o. HsConPatTyArg) + \ (type a) (x :: a) -> rhs -- EmbTyPat (c.o. Pat) + \ a (x :: a) -> rhs -- VarPat (c.o. Pat) (NB. not implemented) + \ @a (x :: a) -> rhs -- to be decided (NB. not implemented) + +* A HsTyPat is not necessarily a plain variable. At the very least, + we support kind signatures and wildcards: + \ (type _) -> rhs + \ (type (b :: Bool)) -> rhs + \ (type (_ :: Bool)) -> rhs + But in constructor patterns we also support full-on types + \ (P @(a -> Either b c)) -> rhs + All these forms are represented with HsTP (c.o. HsTyPat). + +Renaming type applications +-------------------------- +rnExpr delegates renaming of type arguments to rnHsWcType if possible: + f @t -- HsAppType, t is renamed with rnHsWcType + f (type t) -- HsApp and HsEmbTy, t is renamed with rnHsWcType + +But what about: + f t -- HsApp, no HsEmbTy (NB. not implemented) +We simply rename `t` as a term using a recursive call to rnExpr; in particular, +the type of `f` does not affect name resolution (Lexical Scoping Principle). +We will later convert `t` from a `HsExpr` to a `Type`, see "Typechecking type +applications" later in this Note. The details are spelled out in the "Resolved +Syntax Tree" and "T2T-Mapping" sections of GHC Proposal #281. + +Renaming type abstractions +-------------------------- +rnPat delegates renaming of type arguments to rnHsTyPat if possible: + f (P @t) = rhs -- ConPat, t is renamed with rnHsTyPat + f (type t) = rhs -- EmbTyPat, t is renamed with rnHsTyPat + +But what about: + f t = rhs -- VarPat +The solution is as before (see previous section), mutatis mutandis. +Rename `t` as a pattern using a recursive call to `rnPat`, convert it +to a type pattern later. + +One particularly prickly issue is that of implicit quantification. Consider: + + f :: forall a -> ... + f t = ... -- binding site of `t` + where + g :: t -> t -- use site of `t` or a fresh variable? + g = ... + +Does the signature of `g` refer to `t` bound in `f`, or is it a fresh, +implicitly quantified variable? This is normally controlled by +ScopedTypeVariables, but in this example the renamer can't tell `t` from a term +variable. Only later (in the type checker) will we find out that it stands for +the forall-bound type variable `a`. So when RequiredTypeArguments is in effect, +we change implicit quantification to take term variables into account; that is, +we do not implicitly quantify the signature of `g` to `g :: forall t. t->t` +because of the term-level `t` that is in scope. (NB. not implemented) +See Note [Term variable capture and implicit quantification]. + +Typechecking type applications +------------------------------ +Type applications are checked alongside ordinary function applications +in tcInstFun. + +First of all, we assume that the function type is known (i.e. not a metavariable) +and contains a `forall`. Consider: + f :: forall a. a -> a + f x = const x (f @Int 5) +If the type signature is removed, the definition results in an error: + Cannot apply expression of type ‘t1’ + to a visible type argument ‘Int’ + +The same principle applies to required type arguments: + f :: forall a -> a -> a + f (type a) x = const x (f (type Int) 5) +If the type signature is removed, the error is: + Illegal type pattern. + A type pattern must be checked against a visible forall. + +When the type of the function is known and contains a `forall`, all we need to +do is instantiate the forall-bound variable with the supplied type argument. +This is done by tcVTA (if Specified) and tcVDQ (if Required). + +tcVDQ unwraps the HsEmbTy and uses the type contained within it. Crucially, in +tcVDQ we know that we are expecting a type argument. This means that we can +support + f (Maybe Int) -- HsApp, no HsEmbTy (NB. not implemented) +The type argument (Maybe Int) is represented as an HsExpr, but tcVDQ can easily +convert it to HsType. This conversion is called the "T2T-Mapping" in GHC +Proposal #281. + +Typechecking type abstractions +------------------------------ +Type abstractions are checked alongside ordinary patterns in GHC.Tc.Gen.Pat.tcPats. +One of its inputs is a list of ExpPatType that has two constructors + * ExpFunPatTy ... -- the type A of a function A -> B + * ExpForAllPatTy ... -- the binder (a::A) of forall (a::A) -> B +so when we are checking + f :: forall a b -> a -> b -> ... + f (type a) (type b) (x :: a) (y :: b) = ... +our expected pattern types are + [ ExpForAllPatTy ... -- forall a -> + , ExpForAllPatTy ... -- forall b -> + , ExpFunPatTy ... -- a -> + , ExpFunPatTy ... -- b -> + ] + +The [ExpPatType] is initially constructed by GHC.Tc.Utils.Unify.matchExpectedFunTys, +by decomposing the type signature for `f` in our example. If we are given a +definition + g (type a) = ... +we never /infer/ a type g :: forall a -> blah. We can only /check/ +explicit type abstractions in terms. + +The [ExpPatType] allows us to use different code paths for type abstractions +and ordinary patterns: + * tc_pat :: Scaled ExpSigmaTypeFRR -> Checker (Pat GhcRn) (Pat GhcTc) + * tc_forall_pat :: Checker (Pat GhcRn, TcTyVar) (Pat GhcTc) + +tc_forall_pat unwraps the EmbTyPat and uses the type pattern contained +within it. This is another spot where the "T2T-Mapping" can take place. +This would allow us to support + f a (x :: a) = rhs -- no EmbTyPat (NB. not implemented) + +Type patterns in constructor patterns are handled in with tcConTyArg. +Both tc_forall_pat and tcConTyArg delegate most of the work to tcHsTyPat. Note [VTA for out-of-scope functions] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -861,14 +1135,19 @@ give its type. Fortunately in tcInstFun we still have access to the function, so we can check if it is a HsUnboundVar. We use this info to simply skip -over any visible type arguments. We've already inferred the type of -the function (in tcInferAppHead), so we'll /already/ have emitted a +over any visible type arguments. We'll /already/ have emitted a Hole constraint; failing preserves that constraint. We do /not/ want to fail altogether in this case (via failM) because that may abandon an entire instance decl, which (in the presence of -fdefer-type-errors) leads to leading to #17792. +What about required type arguments? Suppose we see + f (type Int) +where `f` is out of scope. Then again we don't want to crash because f's +type (which will be just a fresh unification variable) isn't a visible forall. +Instead we just skip the `(type Int)` argument, as before. + Downside: the typechecked term has lost its visible type arguments; we don't even kind-check them. But let's jump that bridge if we come to it. Meanwhile, let's not crash! diff --git a/compiler/GHC/Tc/Gen/Arrow.hs b/compiler/GHC/Tc/Gen/Arrow.hs index 0f06b5f9d7337de41f188c79398206ffa9d94572..e41b82ec59e88f1148f30fdb0dff62594ddcb462 100644 --- a/compiler/GHC/Tc/Gen/Arrow.hs +++ b/compiler/GHC/Tc/Gen/Arrow.hs @@ -359,7 +359,7 @@ tcCmdMatchLambda env -- Check the patterns, and the GRHSs inside tc_match arg_tys cmd_stk' (L mtch_loc (Match { m_pats = pats, m_grhss = grhss })) = do { (pats', grhss') <- setSrcSpanA mtch_loc $ - tcPats match_ctxt pats arg_tys $ + tcPats match_ctxt pats (map ExpFunPatTy arg_tys) $ tc_grhss grhss cmd_stk' (mkCheckExpType res_ty) ; return $ L mtch_loc (Match { m_ext = noAnn diff --git a/compiler/GHC/Tc/Gen/Expr.hs b/compiler/GHC/Tc/Gen/Expr.hs index bfbbe9906a7bdd61b59fb7e75e8c3bf51f0796f8..0ab15dd2923607bd2a429a00ad5be12c48e60845 100644 --- a/compiler/GHC/Tc/Gen/Expr.hs +++ b/compiler/GHC/Tc/Gen/Expr.hs @@ -452,6 +452,8 @@ tcExpr (HsStatic fvs expr) res_ty (L (noAnnSrcSpan loc) (HsStatic (fvs, mkTyConApp static_ptr_ty_con [expr_ty]) expr')) } +tcExpr (HsEmbTy _ _ _) _ = failWith TcRnIllegalTypeExpr + {- ************************************************************************ * * @@ -789,7 +791,7 @@ tcSynArgE orig op sigma_ty syn_ty thing_inside , res_wrapper ) -- :: res_ty_out "->" res_ty , arg_wrapper1, [], arg_wrapper2 ) ) -- :: arg_ty "->" arg_ty_out <- matchExpectedFunTys herald GenSigCtxt 1 (mkCheckExpType rho_ty) $ - \ [arg_ty] res_ty -> + \ [ExpFunPatTy arg_ty] res_ty -> do { arg_tc_ty <- expTypeToType (scaledThing arg_ty) ; res_tc_ty <- expTypeToType res_ty diff --git a/compiler/GHC/Tc/Gen/Match.hs b/compiler/GHC/Tc/Gen/Match.hs index c77c66b8b417cb1677cc1d5d3f2a1ef08ce1726a..5bfdfd7f537b8c9072413b790587b568a2210859 100644 --- a/compiler/GHC/Tc/Gen/Match.hs +++ b/compiler/GHC/Tc/Gen/Match.hs @@ -80,6 +80,7 @@ import GHC.Types.SrcLoc import Control.Monad import Control.Arrow ( second ) import qualified Data.List.NonEmpty as NE +import Data.Maybe (mapMaybe) {- ************************************************************************ @@ -106,7 +107,7 @@ tcMatchesFun fun_name matches exp_ty -- sensible location. Note: we have to do this odd -- ann-grabbing, because we don't always have annotations in -- hand when we call tcMatchesFun... - traceTc "tcMatchesFun" (ppr fun_name $$ ppr exp_ty) + traceTc "tcMatchesFun" (ppr fun_name $$ ppr exp_ty $$ ppr arity) ; checkArgCounts what matches ; matchExpectedFunTys herald ctxt arity exp_ty $ \ pat_tys rhs_ty -> @@ -139,7 +140,7 @@ tcMatchesFun fun_name matches exp_ty parser guarantees that each equation has exactly one argument. -} -tcMatchesCase :: (AnnoBody body) => +tcMatchesCase :: (AnnoBody body, Outputable (body GhcTc)) => TcMatchCtxt body -- ^ Case context -> Scaled TcSigmaTypeFRR -- ^ Type of scrutinee -> MatchGroup GhcRn (LocatedA (body GhcRn)) -- ^ The case alternatives @@ -149,7 +150,7 @@ tcMatchesCase :: (AnnoBody body) => -- wrapper goes from MatchGroup's ty to expected ty tcMatchesCase ctxt (Scaled scrut_mult scrut_ty) matches res_ty - = tcMatches ctxt [Scaled scrut_mult (mkCheckExpType scrut_ty)] res_ty matches + = tcMatches ctxt [ExpFunPatTy (Scaled scrut_mult (mkCheckExpType scrut_ty))] res_ty matches tcMatchLambda :: ExpectedFunTyOrigin -- see Note [Herald for matchExpectedFunTys] in GHC.Tc.Utils.Unify -> TcMatchCtxt HsExpr @@ -209,8 +210,9 @@ type AnnoBody body ) -- | Type-check a MatchGroup. -tcMatches :: (AnnoBody body ) => TcMatchCtxt body - -> [Scaled ExpSigmaTypeFRR] -- ^ Expected pattern types. +tcMatches :: (AnnoBody body, Outputable (body GhcTc)) => + TcMatchCtxt body + -> [ExpPatType] -- ^ Expected pattern types. -> ExpRhoType -- ^ Expected result-type of the Match. -> MatchGroup GhcRn (LocatedA (body GhcRn)) -> TcM (MatchGroup GhcTc (LocatedA (body GhcTc))) @@ -222,7 +224,7 @@ tcMatches ctxt pat_tys rhs_ty (MG { mg_alts = L l matches -- when in inference mode, so we must do it ourselves, -- here, using expTypeToType = do { tcEmitBindingUsage bottomUE - ; pat_tys <- mapM scaledExpTypeToType pat_tys + ; pat_tys <- mapM scaledExpTypeToType (filter_out_forall_pat_tys pat_tys) ; rhs_ty <- expTypeToType rhs_ty ; return (MG { mg_alts = L l [] , mg_ext = MatchGroupTc pat_tys rhs_ty origin @@ -232,15 +234,23 @@ tcMatches ctxt pat_tys rhs_ty (MG { mg_alts = L l matches = do { umatches <- mapM (tcCollectingUsage . tcMatch ctxt pat_tys rhs_ty) matches ; let (usages,matches') = unzip umatches ; tcEmitBindingUsage $ supUEs usages - ; pat_tys <- mapM readScaledExpType pat_tys + ; pat_tys <- mapM readScaledExpType (filter_out_forall_pat_tys pat_tys) ; rhs_ty <- readExpType rhs_ty + ; traceTc "tcMatches" (ppr matches' $$ ppr pat_tys $$ ppr rhs_ty) ; return (MG { mg_alts = L l matches' , mg_ext = MatchGroupTc pat_tys rhs_ty origin }) } + where + -- We filter out foralls because we have no use for them in HsToCore. + filter_out_forall_pat_tys :: [ExpPatType] -> [Scaled ExpSigmaTypeFRR] + filter_out_forall_pat_tys = mapMaybe match_fun_pat_ty + where + match_fun_pat_ty (ExpFunPatTy t) = Just t + match_fun_pat_ty ExpForAllPatTy{} = Nothing ------------- tcMatch :: (AnnoBody body) => TcMatchCtxt body - -> [Scaled ExpSigmaType] -- Expected pattern types + -> [ExpPatType] -- Expected pattern types -> ExpRhoType -- Expected result-type of the Match. -> LMatch GhcRn (LocatedA (body GhcRn)) -> TcM (LMatch GhcTc (LocatedA (body GhcTc))) @@ -254,7 +264,8 @@ tcMatch ctxt pat_tys rhs_ty match do { (pats', grhss') <- tcPats (mc_what ctxt) pats pat_tys $ tcGRHSs ctxt grhss rhs_ty ; return (Match { m_ext = noAnn - , m_ctxt = mc_what ctxt, m_pats = pats' + , m_ctxt = mc_what ctxt + , m_pats = filter_out_type_pats pats' , m_grhss = grhss' }) } -- For (\x -> e), tcExpr has already said "In the expression \x->e" @@ -264,6 +275,14 @@ tcMatch ctxt pat_tys rhs_ty match LambdaExpr -> thing_inside _ -> addErrCtxt (pprMatchInCtxt match) thing_inside + -- We filter out type patterns because we have no use for them in HsToCore. + -- Type variable bindings have already been converted to HsWrappers. + filter_out_type_pats :: [LPat GhcTc] -> [LPat GhcTc] + filter_out_type_pats = filterByList (map is_fun_pat_ty pat_tys) + where + is_fun_pat_ty ExpFunPatTy{} = True + is_fun_pat_ty ExpForAllPatTy{} = False + ------------- tcGRHSs :: AnnoBody body => TcMatchCtxt body -> GRHSs GhcRn (LocatedA (body GhcRn)) -> ExpRhoType diff --git a/compiler/GHC/Tc/Gen/Pat.hs b/compiler/GHC/Tc/Gen/Pat.hs index 79495ff3544aa30013160ebd1cfb6c634dcfcd61..ab2f6518259c4f5156596958174d5545b48c5788 100644 --- a/compiler/GHC/Tc/Gen/Pat.hs +++ b/compiler/GHC/Tc/Gen/Pat.hs @@ -104,7 +104,7 @@ tcLetPat sig_fn no_gen pat pat_ty thing_inside ----------------- tcPats :: HsMatchContext GhcTc -> [LPat GhcRn] -- ^ atterns - -> [Scaled ExpSigmaTypeFRR] -- ^ types of the patterns + -> [ExpPatType] -- ^ types of the patterns -> TcM a -- ^ checker for the body -> TcM ([LPat GhcTc], a) @@ -120,7 +120,7 @@ tcPats :: HsMatchContext GhcTc -- 4. Check that no existentials escape tcPats ctxt pats pat_tys thing_inside - = tc_lpats pat_tys penv pats thing_inside + = tc_tt_lpats pat_tys penv pats thing_inside where penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = PatOrigin } @@ -350,6 +350,14 @@ tc_lpat pat_ty penv (L span pat) thing_inside thing_inside ; return (L span pat', res) } +tc_tt_lpat :: ExpPatType + -> Checker (LPat GhcRn) (LPat GhcTc) +tc_tt_lpat pat_ty penv (L span pat) thing_inside + = setSrcSpanA span $ + do { (pat', res) <- maybeWrapPatCtxt pat (tc_tt_pat pat_ty penv pat) + thing_inside + ; return (L span pat', res) } + tc_lpats :: [Scaled ExpSigmaTypeFRR] -> Checker [LPat GhcRn] [LPat GhcTc] tc_lpats tys penv pats @@ -358,11 +366,39 @@ tc_lpats tys penv pats penv (zipEqual "tc_lpats" pats tys) +tc_tt_lpats :: [ExpPatType] -> Checker [LPat GhcRn] [LPat GhcTc] +tc_tt_lpats tys penv pats + = assertPpr (equalLength pats tys) (ppr pats $$ ppr tys) $ + tcMultiple (\ penv' (p,t) -> tc_tt_lpat t penv' p) + penv + (zipEqual "tc_tt_lpats" pats tys) + -------------------- -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify. checkManyPattern :: Scaled a -> TcM HsWrapper checkManyPattern pat_ty = tcSubMult NonLinearPatternOrigin ManyTy (scaledMult pat_ty) +tc_tt_pat + :: ExpPatType + -- ^ Fully refined result type + -> Checker (Pat GhcRn) (Pat GhcTc) + -- ^ Translated pattern +tc_tt_pat pat_ty penv (ParPat x lpar pat rpar) thing_inside = do + { (pat', res) <- tc_tt_lpat pat_ty penv pat thing_inside + ; return (ParPat x lpar pat' rpar, res) } +tc_tt_pat (ExpFunPatTy pat_ty) penv pat thing_inside = tc_pat pat_ty penv pat thing_inside +tc_tt_pat (ExpForAllPatTy tv) penv pat thing_inside = tc_forall_pat penv (pat, tv) thing_inside + +tc_forall_pat :: Checker (Pat GhcRn, TcTyVar) (Pat GhcTc) +tc_forall_pat _ (EmbTyPat _ toktype tp, tv) thing_inside + = do { (sig_wcs, sig_ibs, arg_ty) <- tcHsTyPat tp (varType tv) + ; _ <- unifyType Nothing arg_ty (mkTyVarTy tv) + ; result <- tcExtendNameTyVarEnv sig_wcs $ + tcExtendNameTyVarEnv sig_ibs $ + thing_inside + ; return (EmbTyPat arg_ty toktype tp, result) } +tc_forall_pat _ (pat, _) _ = failWith $ TcRnIllformedTypePattern pat + tc_pat :: Scaled ExpSigmaTypeFRR -- ^ Fully refined result type -> Checker (Pat GhcRn) (Pat GhcTc) @@ -702,6 +738,8 @@ AST is used for the subtraction operation. SplicePat (HsUntypedSpliceNested _) _ -> panic "tc_pat: nested splice in splice pat" + EmbTyPat _ _ _ -> failWith TcRnIllegalTypePattern + XPat (HsPatExpanded lpat rpat) -> do { (rpat', res) <- tc_pat pat_ty penv rpat thing_inside ; return (XPat $ ExpansionPat lpat rpat', res) } diff --git a/compiler/GHC/Tc/TyCl/PatSyn.hs b/compiler/GHC/Tc/TyCl/PatSyn.hs index c34e9159cb588de80c8a765cd96546848e474bc9..71e4b5f319bb28e2cc4952aa162ba686f5a27a6f 100644 --- a/compiler/GHC/Tc/TyCl/PatSyn.hs +++ b/compiler/GHC/Tc/TyCl/PatSyn.hs @@ -1073,6 +1073,10 @@ tcPatToExpr args pat = go pat | otherwise = return $ HsOverLit noAnn n go1 (SplicePat (HsUntypedSpliceTop _ pat) _) = go1 pat go1 (SplicePat (HsUntypedSpliceNested _) _) = panic "tcPatToExpr: invalid nested splice" + go1 (EmbTyPat _ toktype tp) = return $ HsEmbTy noExtField toktype (hstp_to_hswc tp) + where hstp_to_hswc :: HsTyPat GhcRn -> LHsWcType GhcRn + hstp_to_hswc (HsTP { hstp_ext = HsTPRn { hstp_nwcs = wcs }, hstp_body = hs_ty }) + = HsWC { hswc_ext = wcs, hswc_body = hs_ty } go1 (XPat (HsPatExpanded _ pat))= go1 pat -- See Note [Invertible view patterns] diff --git a/compiler/GHC/Tc/Types/Evidence.hs b/compiler/GHC/Tc/Types/Evidence.hs index 81266433f117900063e2bcc63d904a6c048b0f56..e9937d0f953af5532be1f33c1703ab36aa0e0b78 100644 --- a/compiler/GHC/Tc/Types/Evidence.hs +++ b/compiler/GHC/Tc/Types/Evidence.hs @@ -7,7 +7,7 @@ module GHC.Tc.Types.Evidence ( -- * HsWrapper HsWrapper(..), - (<.>), mkWpTyApps, mkWpEvApps, mkWpEvVarApps, mkWpTyLams, + (<.>), mkWpTyApps, mkWpEvApps, mkWpEvVarApps, mkWpTyLams, mkWpVisTyLam, mkWpEvLams, mkWpLet, mkWpFun, mkWpCastN, mkWpCastR, mkWpEta, collectHsWrapBinders, idHsWrapper, isIdHsWrapper, @@ -258,6 +258,21 @@ mkWpEvVarApps vs = mk_co_app_fn WpEvApp (map (EvExpr . evId) vs) mkWpTyLams :: [TyVar] -> HsWrapper mkWpTyLams ids = mk_co_lam_fn WpTyLam ids +-- Construct a type lambda and cast its type +-- from `forall tv. res` to `forall tv -> res`. +-- +-- (\ @tv -> e ) +-- `cast` (forall (tv[spec]~[req] :: <*>_N). <res>_R -- ForAllCo is the evidence that... +-- :: (forall tv. res) ~R# (forall tv -> res)) -- invisible and visible foralls are representationally equal +-- +mkWpVisTyLam :: TyVar -> Type -> HsWrapper +mkWpVisTyLam tv res = + WpCast (mkForAllCo tv coreTyLamForAllTyFlag Required kind_co body_co) + <.> WpTyLam tv + where + kind_co = mkNomReflCo (varType tv) + body_co = mkRepReflCo res + mkWpEvLams :: [Var] -> HsWrapper mkWpEvLams ids = mk_co_lam_fn WpEvLam ids diff --git a/compiler/GHC/Tc/Types/Origin.hs b/compiler/GHC/Tc/Types/Origin.hs index 10b0c795a815d9dd4a5a64e5102428cdb7471cfd..686b384d061224a955a59aa4341060485addc830 100644 --- a/compiler/GHC/Tc/Types/Origin.hs +++ b/compiler/GHC/Tc/Types/Origin.hs @@ -739,6 +739,7 @@ exprCtOrigin (HsTypedSplice {}) = Shouldn'tHappenOrigin "TH typed splice" exprCtOrigin (HsUntypedSplice {}) = Shouldn'tHappenOrigin "TH untyped splice" exprCtOrigin (HsProc {}) = Shouldn'tHappenOrigin "proc" exprCtOrigin (HsStatic {}) = Shouldn'tHappenOrigin "static expression" +exprCtOrigin (HsEmbTy {}) = Shouldn'tHappenOrigin "type expression" exprCtOrigin (XExpr (HsExpanded a _)) = exprCtOrigin a -- | Extract a suitable CtOrigin from a MatchGroup diff --git a/compiler/GHC/Tc/Utils/TcType.hs b/compiler/GHC/Tc/Utils/TcType.hs index 5dedeef9a3f5251b0ab463d2356072da183b2e0c..b4d98b2ab0d297044a281aef2bde62a8868d5dd3 100644 --- a/compiler/GHC/Tc/Utils/TcType.hs +++ b/compiler/GHC/Tc/Utils/TcType.hs @@ -33,6 +33,8 @@ module GHC.Tc.Utils.TcType ( mkCheckExpType, checkingExpType_maybe, checkingExpType, + ExpPatType(..), + SyntaxOpType(..), synKnownType, mkSynFunTys, -------------------------------- @@ -458,6 +460,15 @@ checkingExpType :: String -> ExpType -> TcType checkingExpType _ (Check ty) = ty checkingExpType err et = pprPanic "checkingExpType" (text err $$ ppr et) +-- Expected type of a pattern in a lambda or a function left-hand side. +data ExpPatType = + ExpFunPatTy (Scaled ExpSigmaTypeFRR) -- the type A of a function A -> B + | ExpForAllPatTy TcTyVar -- the binder (a::A) of forall (a::A) -> B + +instance Outputable ExpPatType where + ppr (ExpFunPatTy t) = ppr t + ppr (ExpForAllPatTy tv) = text "forall" <+> ppr tv + {- ********************************************************************* * * SyntaxOpType diff --git a/compiler/GHC/Tc/Utils/Unify.hs b/compiler/GHC/Tc/Utils/Unify.hs index 5c31049cabcb04f8c88366636a61df932ad18aa5..c591b1be49c9d7fd8f76a67b19a11fa3c2a89222 100644 --- a/compiler/GHC/Tc/Utils/Unify.hs +++ b/compiler/GHC/Tc/Utils/Unify.hs @@ -183,7 +183,7 @@ matchActualFunTySigma herald mb_thing err_info fun_ty ------------ mk_ctxt :: TcType -> TidyEnv -> ZonkM (TidyEnv, SDoc) - mk_ctxt res_ty env = mkFunTysMsg env herald (reverse arg_tys_so_far) + mk_ctxt res_ty env = mkFunTysMsg env herald [Anon t visArgTypeLike | t <- reverse arg_tys_so_far] res_ty n_val_args_in_call (n_val_args_in_call, arg_tys_so_far) = err_info @@ -376,7 +376,7 @@ matchExpectedFunTys :: forall a. -> UserTypeCtxt -> Arity -> ExpRhoType -- Skolemised - -> ([Scaled ExpSigmaTypeFRR] -> ExpRhoType -> TcM a) + -> ([ExpPatType] -> ExpRhoType -> TcM a) -> TcM (HsWrapper, a) -- If matchExpectedFunTys n ty = (wrap, _) -- then wrap : (t1 -> ... -> tn -> ty_r) ~> ty, @@ -386,11 +386,11 @@ matchExpectedFunTys herald ctx arity orig_ty thing_inside Check ty -> go [] arity ty _ -> defer [] arity orig_ty where - -- Skolemise any foralls /before/ the zero-arg case + -- Skolemise any /invisible/ foralls /before/ the zero-arg case -- so that we guarantee to return a rho-type go acc_arg_tys n ty - | (tvs, theta, _) <- tcSplitSigmaTy ty - , not (null tvs && null theta) + | (tvs, theta, _) <- tcSplitSigmaTy ty -- Invisible binders only! + , not (null tvs && null theta) -- Visible ones handled below = do { (wrap_gen, (wrap_res, result)) <- tcTopSkolemise ctx ty $ \ty' -> go acc_arg_tys n ty' ; return (wrap_gen <.> wrap_res, result) } @@ -404,11 +404,22 @@ matchExpectedFunTys herald ctx arity orig_ty thing_inside go acc_arg_tys n ty | Just ty' <- coreView ty = go acc_arg_tys n ty' + -- Decompose /visible/ (forall a -> blah), to give an ExpForAllPat + -- NB: invisible binders are handled by tcSplitSigmaTy/tcTopSkolemise above + -- NB: visible foralls "count" for the Arity argument; they correspond + -- to syntactically visible patterns in the source program + -- See Note [Visible type application and abstraction] in GHC.Tc.Gen.App + go acc_arg_tys n ty + | Just (Bndr tv vis, ty') <- splitForAllForAllTyBinder_maybe ty + , Required <- vis + = let init_subst = mkEmptySubst (mkInScopeSet (tyCoVarsOfType ty)) + in goVdq init_subst acc_arg_tys n ty tv ty' + go acc_arg_tys n (FunTy { ft_af = af, ft_mult = mult, ft_arg = arg_ty, ft_res = res_ty }) = assert (isVisibleFunArg af) $ do { let arg_pos = 1 + length acc_arg_tys -- for error messages only ; (arg_co, arg_ty) <- hasFixedRuntimeRep (FRRExpectedFunTy herald arg_pos) arg_ty - ; (wrap_res, result) <- go ((Scaled mult $ mkCheckExpType arg_ty) : acc_arg_tys) + ; (wrap_res, result) <- go ((ExpFunPatTy $ Scaled mult $ mkCheckExpType arg_ty) : acc_arg_tys) (n-1) res_ty ; let wrap_arg = mkWpCastN arg_co fun_wrap = mkWpFun wrap_arg wrap_res (Scaled mult arg_ty) res_ty @@ -439,13 +450,24 @@ matchExpectedFunTys herald ctx arity orig_ty thing_inside go acc_arg_tys n ty = addErrCtxtM (mk_ctxt acc_arg_tys ty) $ defer acc_arg_tys n (mkCheckExpType ty) + goVdq subst acc_arg_tys n expected_ty tv ty = + do { rec { (subst', [tv']) <- tcInstSkolTyVarsX skol_info subst [tv] + ; let tv_prs = [(tyVarName tv, tv')] + ; skol_info <- mkSkolemInfo (SigSkol ctx expected_ty tv_prs) } + ; let ty' = substTy subst' ty + ; (ev_binds, (wrap_res, result)) <- + checkConstraints (getSkolemInfo skol_info) [tv'] [] $ + go (ExpForAllPatTy tv' : acc_arg_tys) (n - 1) ty' + ; let wrap_gen = mkWpVisTyLam tv' ty' <.> mkWpLet ev_binds + ; return (wrap_gen <.> wrap_res, result) } + ------------ - defer :: [Scaled ExpSigmaTypeFRR] -> Arity -> ExpRhoType -> TcM (HsWrapper, a) + defer :: [ExpPatType] -> Arity -> ExpRhoType -> TcM (HsWrapper, a) defer acc_arg_tys n fun_ty = do { let last_acc_arg_pos = length acc_arg_tys ; more_arg_tys <- mapM new_exp_arg_ty [last_acc_arg_pos + 1 .. last_acc_arg_pos + n] ; res_ty <- newInferExpType - ; result <- thing_inside (reverse acc_arg_tys ++ more_arg_tys) res_ty + ; result <- thing_inside (reverse acc_arg_tys ++ map ExpFunPatTy more_arg_tys) res_ty ; more_arg_tys <- mapM (\(Scaled m t) -> Scaled m <$> readExpType t) more_arg_tys ; res_ty <- readExpType res_ty ; let unif_fun_ty = mkScaledFunTys more_arg_tys res_ty @@ -459,30 +481,40 @@ matchExpectedFunTys herald ctx arity orig_ty thing_inside <*> newInferExpTypeFRR (FRRExpectedFunTy herald arg_pos) ------------ - mk_ctxt :: [Scaled ExpSigmaTypeFRR] -> TcType -> TidyEnv -> ZonkM (TidyEnv, SDoc) + mk_ctxt :: [ExpPatType] -> TcType -> TidyEnv -> ZonkM (TidyEnv, SDoc) mk_ctxt arg_tys res_ty env = mkFunTysMsg env herald arg_tys' res_ty arity where - arg_tys' = map (\(Scaled u v) -> Scaled u (checkingExpType "matchExpectedFunTys" v)) $ - reverse arg_tys + arg_tys' = map prepare_arg_ty (reverse arg_tys) + prepare_arg_ty (ExpFunPatTy (Scaled u v)) = Anon (Scaled u (checkingExpType "matchExpectedFunTys" v)) visArgTypeLike + prepare_arg_ty (ExpForAllPatTy tv) = Named (Bndr tv Required) -- this is safe b/c we're called from "go" mkFunTysMsg :: TidyEnv -> ExpectedFunTyOrigin - -> [Scaled TcType] -> TcType -> Arity + -> [PiTyBinder] -- only visible quantifiers `t1 -> t2` and `forall (x :: t1) -> t2` + -> TcType + -> Arity -> ZonkM (TidyEnv, SDoc) mkFunTysMsg env herald arg_tys res_ty n_val_args_in_call - = do { (env', fun_rho) <- zonkTidyTcType env $ - mkScaledFunTys arg_tys res_ty + = do { (env', fun_ty) <- zonkTidyTcType env $ + mkPiTys arg_tys res_ty + + ; let (all_arg_tys, _) = + -- No invisible quantifiers here (neither `ctx => t` nor `forall x. t`) + -- because `mkFunTysMsg` never gets those as input in the first place, + -- so there is no need to filter them out. + splitPiTys fun_ty - ; let (all_arg_tys, _) = splitFunTys fun_rho + -- `all_arg_tys` contains visible quantifiers only, so their number matches + -- the number of arguments that the user needs to pass to the function. n_fun_args = length all_arg_tys msg | n_val_args_in_call <= n_fun_args -- Enough args, in the end = text "In the result of a function call" | otherwise = hang (full_herald <> comma) - 2 (sep [ text "but its type" <+> quotes (pprType fun_rho) + 2 (sep [ text "but its type" <+> quotes (pprType fun_ty) , if n_fun_args == 0 then text "has none" else text "has only" <+> speakN n_fun_args]) diff --git a/compiler/GHC/Tc/Validity.hs b/compiler/GHC/Tc/Validity.hs index 9f5846ba85b24b174f790f95153ad8af9ff89d88..394de6c8e0af3a25ac048e074b98052af07e2432 100644 --- a/compiler/GHC/Tc/Validity.hs +++ b/compiler/GHC/Tc/Validity.hs @@ -993,7 +993,8 @@ checkConstraintsOK ve theta ty checkVdqOK :: ValidityEnv -> [TyVarBinder] -> Type -> TcM () checkVdqOK ve tvbs ty = do - checkTcM (vdqAllowed ctxt || no_vdq) + required_type_arguments <- xoptM LangExt.RequiredTypeArguments + checkTcM (required_type_arguments || vdqAllowed ctxt || no_vdq) (env, TcRnVDQInTermType (Just (tidyType env ty))) where no_vdq = all (isInvisibleForAllTyFlag . binderFlag) tvbs diff --git a/compiler/GHC/Tc/Zonk/Type.hs b/compiler/GHC/Tc/Zonk/Type.hs index 58069d1b05f515995b00ac1c38116339ac840985..7d5d15396e28cc3d369a25f8b3e12b81a2765bba 100644 --- a/compiler/GHC/Tc/Zonk/Type.hs +++ b/compiler/GHC/Tc/Zonk/Type.hs @@ -1064,6 +1064,8 @@ zonkExpr (HsStatic (fvs, ty) expr) = do new_ty <- zonkTcTypeToTypeX ty HsStatic (fvs, new_ty) <$> zonkLExpr expr +zonkExpr (HsEmbTy x _ _) = dataConCantHappen x + zonkExpr (XExpr (WrapExpr (HsWrap co_fn expr))) = runZonkBndrT (zonkCoFn co_fn) $ \ new_co_fn -> do new_expr <- zonkExpr expr @@ -1577,6 +1579,10 @@ zonk_pat (NPlusKPat ty (L loc n) (L l lit1) lit2 e1 e2) ; n' <- zonkIdBndrX n ; return (NPlusKPat ty' (L loc n') (L l lit1') lit2' e1' e2') } +zonk_pat (EmbTyPat ty toktype tp) + = do { ty' <- noBinders $ zonkTcTypeToTypeX ty + ; return (EmbTyPat ty' toktype tp) } + zonk_pat (XPat ext) = case ext of { ExpansionPat orig pat-> do { pat' <- zonk_pat pat diff --git a/compiler/GHC/ThToHs.hs b/compiler/GHC/ThToHs.hs index 4b35c92cba92e487baa449fdeca5d6607d74358e..e884c5b2cec073ec78a3b11ca2f2992291d7a70b 100644 --- a/compiler/GHC/ThToHs.hs +++ b/compiler/GHC/ThToHs.hs @@ -1164,6 +1164,8 @@ cvtl e = wrapLA (cvt e) ; return $ HsTypedSplice (noAnn, noAnn) e' } cvt (TypedBracketE e) = do { e' <- cvtl e ; return $ HsTypedBracket noAnn e' } + cvt (TypeE t) = do { t' <- cvtType t + ; return $ HsEmbTy noExtField noHsTok (mkHsWildCardBndrs t') } {- | #16895 Ensure an infix expression's operator is a variable/constructor. Consider this example: @@ -1480,6 +1482,8 @@ cvtp (SigP p t) = do { p' <- cvtPat p; t' <- cvtType t ; return $ SigPat noAnn p' (mkHsPatSigType noAnn t') } cvtp (ViewP e p) = do { e' <- cvtl e; p' <- cvtPat p ; return $ ViewPat noAnn e' p'} +cvtp (TypeP t) = do { t' <- cvtType t + ; return $ EmbTyPat noExtField noHsTok (mkHsTyPat noAnn t') } cvtPatFld :: (TH.Name, TH.Pat) -> CvtM (LHsRecField GhcPs (LPat GhcPs)) cvtPatFld (s,p) diff --git a/compiler/GHC/Types/Error/Codes.hs b/compiler/GHC/Types/Error/Codes.hs index 8be60f2c85d8f935c3107e49c1b952297b61af95..90a918c8f0206e4882078cabafe1e30647694a53 100644 --- a/compiler/GHC/Types/Error/Codes.hs +++ b/compiler/GHC/Types/Error/Codes.hs @@ -624,6 +624,10 @@ type family GhcDiagnosticCode c = n | n -> c where GhcDiagnosticCode "HasConstructorContext" = 17440 GhcDiagnosticCode "HasExistentialTyVar" = 07525 GhcDiagnosticCode "HasStrictnessAnnotation" = 04049 + GhcDiagnosticCode "TcRnIllformedTypePattern" = 88754 + GhcDiagnosticCode "TcRnIllegalTypePattern" = 70206 + GhcDiagnosticCode "TcRnIllformedTypeArgument" = 29092 + GhcDiagnosticCode "TcRnIllegalTypeExpr" = 35499 -- TcRnBadRecordUpdate GhcDiagnosticCode "NoConstructorHasAllFields" = 14392 diff --git a/compiler/GHC/Types/Var.hs b/compiler/GHC/Types/Var.hs index bbc5454c9fc009396d8643bfb26acac080ee804f..ec50a364af5cec8963c235c0d054255598a64307 100644 --- a/compiler/GHC/Types/Var.hs +++ b/compiler/GHC/Types/Var.hs @@ -920,8 +920,7 @@ This table summarises the visibility rules: | tvis = Inferred: f :: forall {a}. type Arg not allowed: f f :: forall {co}. type Arg not allowed: f | tvis = Specified: f :: forall a. type Arg optional: f or f @Int -| tvis = Required: T :: forall k -> type Arg required: T * -| This last form is illegal in terms: See Note [No Required PiTyBinder in terms] +| tvis = Required: f :: forall k -> type Arg required: f (type Int) | | Bndr k cvis :: TyConBinder, in the TyConBinders of a TyCon | cvis :: TyConBndrVis @@ -952,22 +951,28 @@ This table summarises the visibility rules: f3 :: forall a. a -> a; f3 x = x So f3 gets the type f3 :: forall a. a -> a, with 'a' Specified +* Required. Function defn, with signature (explicit forall): + f4 :: forall a -> a -> a; f4 (type _) x = x + So f4 gets the type f4 :: forall a -> a -> a, with 'a' Required + This is the experimental RequiredTypeArguments extension, + see GHC Proposal #281 "Visible forall in types of terms" + * Inferred. Function defn, with signature (explicit forall), marked as inferred: - f4 :: forall {a}. a -> a; f4 x = x - So f4 gets the type f4 :: forall {a}. a -> a, with 'a' Inferred + f5 :: forall {a}. a -> a; f5 x = x + So f5 gets the type f5 :: forall {a}. a -> a, with 'a' Inferred It's Inferred because the user marked it as such, even though it does appear - in the user-written signature for f4 + in the user-written signature for f5 * Inferred/Specified. Function signature with inferred kind polymorphism. - f5 :: a b -> Int - So 'f5' gets the type f5 :: forall {k} (a:k->*) (b:k). a b -> Int + f6 :: a b -> Int + So 'f6' gets the type f6 :: forall {k} (a :: k -> Type) (b :: k). a b -> Int Here 'k' is Inferred (it's not mentioned in the type), but 'a' and 'b' are Specified. * Specified. Function signature with explicit kind polymorphism - f6 :: a (b :: k) -> Int + f7 :: a (b :: k) -> Int This time 'k' is Specified, because it is mentioned explicitly, - so we get f6 :: forall (k:*) (a:k->*) (b:k). a b -> Int + so we get f7 :: forall (k :: Type) (a :: k -> Type) (b :: k). a b -> Int * Similarly pattern synonyms: Inferred - from inferred types (e.g. no pattern type signature) @@ -1027,7 +1032,7 @@ See also Note [Required, Specified, and Inferred for types] in GHC.Tc.TyCl const :: forall a b. a -> b -> a Inferred: like Specified, but every binder is written in braces: - f :: forall {k} (a:k). S k a -> Int + f :: forall {k} (a :: k). S k a -> Int Required: binders are put between `forall` and `->`: T :: forall k -> * @@ -1039,19 +1044,6 @@ See also Note [Required, Specified, and Inferred for types] in GHC.Tc.TyCl * Inferred variables correspond to "generalized" variables from the Visible Type Applications paper (ESOP'16). - -Note [No Required PiTyBinder in terms] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We don't allow Required foralls for term variables, including pattern -synonyms and data constructors. Why? Because then an application -would need a /compulsory/ type argument (possibly without an "@"?), -thus (f Int); and we don't have concrete syntax for that. - -We could change this decision, but Required, Named PiTyBinders are rare -anyway. (Most are Anons.) - -However the type of a term can (just about) have a required quantifier; -see Note [Required quantifiers in the type of a term] in GHC.Tc.Gen.Expr. -} diff --git a/compiler/Language/Haskell/Syntax/Expr.hs b/compiler/Language/Haskell/Syntax/Expr.hs index c79b54518a4b1e8e2a715765e9c8544590e8c8d2..8707d300384dd8ba125dfff660bf4c7b261205f7 100644 --- a/compiler/Language/Haskell/Syntax/Expr.hs +++ b/compiler/Language/Haskell/Syntax/Expr.hs @@ -579,6 +579,12 @@ data HsExpr p -- Expressions annotated with pragmas, written as {-# ... #-} | HsPragE (XPragE p) (HsPragE p) (LHsExpr p) + -- Embed the syntax of types into expressions. + -- Used with RequiredTypeArguments, e.g. fn (type (Int -> Bool)) + | HsEmbTy (XEmbTy p) + !(LHsToken "type" p) + (LHsWcType (NoGhcTc p)) + | XExpr !(XXExpr p) -- Note [Trees That Grow] in Language.Haskell.Syntax.Extension for the -- general idea, and Note [Rebindable syntax and HsExpansion] in GHC.Hs.Expr diff --git a/compiler/Language/Haskell/Syntax/Extension.hs b/compiler/Language/Haskell/Syntax/Extension.hs index 4069bb8cf00bd8f52e5ae808328c81aa88098214..82edc341f2c4ddc3974782731b418a14dcef9491 100644 --- a/compiler/Language/Haskell/Syntax/Extension.hs +++ b/compiler/Language/Haskell/Syntax/Extension.hs @@ -447,6 +447,7 @@ type family XStatic x type family XTick x type family XBinTick x type family XPragE x +type family XEmbTy x type family XXExpr x -- ------------------------------------- @@ -606,6 +607,7 @@ type family XLitPat x type family XNPat x type family XNPlusKPat x type family XSigPat x +type family XEmbTyPat x type family XCoPat x type family XXPat x type family XHsFieldBind x diff --git a/compiler/Language/Haskell/Syntax/Pat.hs b/compiler/Language/Haskell/Syntax/Pat.hs index 8ff31fd8dbebee850b44ca4f8ea38cacb3a6f40f..4a4230abb176dfe1e11be46ae2b0466d891e44c9 100644 --- a/compiler/Language/Haskell/Syntax/Pat.hs +++ b/compiler/Language/Haskell/Syntax/Pat.hs @@ -219,6 +219,12 @@ data Pat p -- ^ Pattern with a type signature + -- Embed the syntax of types into patterns. + -- Used with RequiredTypeArguments, e.g. fn (type t) = rhs + | EmbTyPat (XEmbTyPat p) + !(LHsToken "type" p) + (HsTyPat (NoGhcTc p)) + -- Extension point; see Note [Trees That Grow] in Language.Haskell.Syntax.Extension | XPat !(XXPat p) diff --git a/docs/users_guide/9.10.1-notes.rst b/docs/users_guide/9.10.1-notes.rst index d33c6565a997dba1660b5b409f14ce0311612bb9..57fbd5177bd5602b4f79c0f21039382e5b9136dd 100644 --- a/docs/users_guide/9.10.1-notes.rst +++ b/docs/users_guide/9.10.1-notes.rst @@ -6,6 +6,18 @@ Version 9.10.1 Language ~~~~~~~~ +- Part 1 of GHC Proposal `#281 + <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0281-visible-forall.rst>`_ + "Visible forall in types of terms" has been implemented. + The following code is now accepted by GHC:: + + idv :: forall a -> a -> a + idv (type a) (x :: a) = x + + x = idv (type Int) 42 + + This feature is guarded behind :extension:`RequiredTypeArguments` and :extension:`ExplicitNamespaces`. + Compiler ~~~~~~~~ @@ -30,6 +42,10 @@ Runtime system ``template-haskell`` library ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- Extend ``Pat`` with ``TypeP`` and ``Exp`` with ``TypeE``, + introduce functions ``typeP`` and ``typeE`` (Template Haskell support for GHC Proposal `#281 + <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0281-visible-forall.rst>`_). + Included libraries ~~~~~~~~~~~~~~~~~~ diff --git a/docs/users_guide/exts/explicit_namespaces.rst b/docs/users_guide/exts/explicit_namespaces.rst index 64058f25de69b4f1ad5762ac1a815f8df30d047b..04c6ba099c46b5ca572a7710d7532ee46d02d777 100644 --- a/docs/users_guide/exts/explicit_namespaces.rst +++ b/docs/users_guide/exts/explicit_namespaces.rst @@ -11,7 +11,7 @@ Explicit namespaces in import/export :implied by: :extension:`TypeOperators`, :extension:`TypeFamilies` :since: 7.6.1 - Enable use of explicit namespaces in module export lists. + Enable use of explicit namespaces in module export lists, patterns, and expressions. In an import or export list, such as :: @@ -41,3 +41,11 @@ In addition, with :extension:`PatternSynonyms` you can prefix the name of a data constructor in an import or export list with the keyword ``pattern``, to allow the import or export of a data constructor without its parent type constructor (see :ref:`patsyn-impexp`). + +Furthermore, :extension:`ExplicitNamespaces` permits the use of the ``type`` +keyword in patterns and expressions:: + + f (type t) x = ... -- in a pattern + r = f (type Integer) 10 -- in an expression + +This is used in conjunction with :extension:`RequiredTypeArguments`. \ No newline at end of file diff --git a/docs/users_guide/exts/required_type_arguments.rst b/docs/users_guide/exts/required_type_arguments.rst new file mode 100644 index 0000000000000000000000000000000000000000..7876b841322601e2182b953a5ebe21ba98a2613f --- /dev/null +++ b/docs/users_guide/exts/required_type_arguments.rst @@ -0,0 +1,113 @@ +Required type arguments +======================= + +.. extension:: RequiredTypeArguments + :shortdesc: Enable required type arguments in terms. + + :since: 9.10.1 + :status: Experimental + + Allow visible dependent quantification ``forall x ->`` in types of terms. + +**This feature is only partially implemented in GHC.** In this section we +describe the implemented subset, while the full specification can be found in +`GHC Proposal #281 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0281-visible-forall.rst>`__. + +The :extension:`RequiredTypeArguments` extension enables the use of visible +dependent quantification in types of terms:: + + id :: forall a. a -> a -- invisible dependent quantification + id_vdq :: forall a -> a -> a -- visible dependent quantification + +Note that the arrow in ``forall a ->`` is part of the syntax and not a function +arrow, just like the dot in ``forall a.`` is not a type operator. The essence of +a ``forall`` is the same regardless of whether it is followed by a dot or an +arrow: it introduces a type variable. But the way we bind and specify this type +variable at the term level differs. + +When we define ``id``, we can use a lambda to bind a variable that stands for +the function argument:: + + -- For reference: id :: forall a. a -> a + id = \x -> x + +At the same time, there is no mention of ``a`` in this definition at all. It is +bound by the compiler behind the scenes, and that is why we call the ordinary +``forall a.`` an *invisible* quantifier. Compare that to ``forall a ->``, which +is considered *visible*:: + + -- For reference: id_vdq :: forall a -> a -> a + id_vdq = \(type t) x -> x + +This time we have two binders in the lambda: +* ``type t``, corresponding to ``forall a ->`` in the signature +* ``x``, corresponding to ``a ->`` in the signature + +And of course, now we also have the option of using the bound ``t`` in a +subsequent pattern, as well as on the right-hand side of the lambda:: + + -- For reference: id_vdq :: forall a -> a -> a + id_vdq = \(type t) (x :: t) -> x :: t + -- ↑ ↑ ↑ + -- bound used used + +At use sites, we also instantiate this type variable explicitly:: + + n = id_vdq (type Integer) 42 + s = id_vdq (type String) "Hello" + +Relation to :extension:`TypeApplications` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:extension:`RequiredTypeArguments` are similar to :extension:`TypeApplications` +in that we pass a type to a function as an explicit argument. The difference is +that type applications are optional: it is up to the caller whether to write +``id @Bool True`` or ``id True``. By default, the compiler infers that the +type variable is instantiated to ``Bool``. The existence of a type argument is +not reflected syntactically in the expression, it is invisible unless we use a +*visibility override*, i.e. ``@``. + +Required type arguments are compulsory. They must appear syntactically at call +sites:: + + x1 = id_vdq (type Bool) True -- OK + x2 = id_vdq True -- not OK + +You may use an underscore to infer a required type argument:: + + x3 = id_vdq (type _) True -- OK + +That is, it is mostly a matter of syntax whether to use ``forall a.`` with type +applications or ``forall a ->``. One advantage of required type arguments is that +they are never ambiguous. Consider the type of ``Foreign.Storable.sizeOf``:: + + sizeOf :: forall a. Storable a => a -> Int + +The value parameter is not actually used, its only purpose is to drive type +inference. At call sites, one might write ``sizeOf (undefined :: Bool)`` or +``sizeOf @Bool undefined``. Either way, the ``undefined`` is entirely +superfluous and exists only to avoid an ambiguous type variable. + +With :extension:`RequiredTypeArguments`, we can imagine a slightly different API:: + + sizeOf :: forall a -> Storable a => Int + +If ``sizeOf`` had this type, we could write ``sizeOf (type Bool)`` without +passing a dummy value. + +Relation to :extension:`ExplicitNamespaces` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``type`` keyword that we used in the examples is not actually part of +:extension:`RequiredTypeArguments`. It is guarded behind +:extension:`ExplicitNamespaces`. As described in the proposal, required type +arguments can be passed without a syntactic marker, making them syntactically +indistinguishble from ordinary function arguments:: + + n = id_vdq Integer 42 + +In this example we pass ``Integer`` as opposed to ``(type Integer)``. +**This is not currently implemented**, but it demonstrates how +:extension:`RequiredTypeArguments` is not tied to the ``type`` syntax. +For this reason, using the ``type`` syntax requires enabling the +:extension:`ExplicitNamespaces` extension separately. \ No newline at end of file diff --git a/docs/users_guide/exts/types.rst b/docs/users_guide/exts/types.rst index 8d2b6f9f908e13327a48c67ba457b224f708d017..c11bed1da78b6702e1f704d6060b9ee80cb9104c 100644 --- a/docs/users_guide/exts/types.rst +++ b/docs/users_guide/exts/types.rst @@ -22,6 +22,7 @@ Types type_literals type_applications type_abstractions + required_type_arguments rank_polymorphism impredicative_types linear_types diff --git a/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs b/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs index e3bd35cbbb00725c17adc05b6b84d5e3c720318c..2b14665a789c93eb83d6a6cd361db83accc41936 100644 --- a/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs +++ b/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs @@ -77,6 +77,7 @@ data Extension | InstanceSigs | ApplicativeDo | LinearTypes + | RequiredTypeArguments -- Visible forall (VDQ) in types of terms | StandaloneDeriving | DeriveDataTypeable diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib.hs b/libraries/template-haskell/Language/Haskell/TH/Lib.hs index 1bf8d29b884ca417dc88393b0f8f8a3aa3f0c54a..88d6baa7954cfa4ea26b29cd50c355b8566a4cea 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Lib.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Lib.hs @@ -33,7 +33,7 @@ module Language.Haskell.TH.Lib ( -- *** Patterns litP, varP, tupP, unboxedTupP, unboxedSumP, conP, uInfixP, parensP, infixP, tildeP, bangP, asP, wildP, recP, - listP, sigP, viewP, + listP, sigP, viewP, typeP, fieldPat, -- *** Pattern Guards @@ -44,7 +44,7 @@ module Language.Haskell.TH.Lib ( appE, appTypeE, uInfixE, parensE, infixE, infixApp, sectionL, sectionR, lamE, lam1E, lamCaseE, lamCasesE, tupE, unboxedTupE, unboxedSumE, condE, multiIfE, letE, caseE, appsE, listE, sigE, recConE, recUpdE, stringE, - fieldExp, getFieldE, projectionE, typedSpliceE, typedBracketE, + fieldExp, getFieldE, projectionE, typedSpliceE, typedBracketE, typeE, -- **** Ranges fromE, fromThenE, fromToE, fromThenToE, diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs b/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs index 2ec036ee5ae6cd406d4045e9a276680c4208eb26..4da31ac144dd896d24b79d579b1275bea7d5374c 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Lib/Internal.hs @@ -160,6 +160,9 @@ sigP :: Quote m => m Pat -> m Type -> m Pat sigP p t = do p' <- p t' <- t pure (SigP p' t') +typeP :: Quote m => m Type -> m Pat +typeP t = do t' <- t + pure (TypeP t') viewP :: Quote m => m Exp -> m Pat -> m Pat viewP e p = do e' <- e p' <- p @@ -401,6 +404,8 @@ fromThenToE :: Quote m => m Exp -> m Exp -> m Exp -> m Exp fromThenToE x y z = do { a <- x; b <- y; c <- z; pure (ArithSeqE (FromThenToR a b c)) } +typeE :: Quote m => m Type -> m Exp +typeE = fmap TypeE ------------------------------------------------------------------------------- -- * Dec diff --git a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs index 001d82b50b92ef8099b5fbd831d2c7cbc5a83998..958d7a0882482ae932bcb60008c692e2119fa48d 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs @@ -234,6 +234,7 @@ pprExp _ (GetFieldE e f) = pprExp appPrec e <> text ('.': f) pprExp _ (ProjectionE xs) = parens $ hcat $ map ((char '.'<>) . text) $ toList xs pprExp _ (TypedBracketE e) = text "[||" <> ppr e <> text "||]" pprExp _ (TypedSpliceE e) = text "$$" <> pprExp appPrec e +pprExp i (TypeE t) = parensIf (i > noPrec) $ text "type" <+> ppr t pprFields :: [(Name,Exp)] -> Doc pprFields = sep . punctuate comma . map (\(s,e) -> pprName' Applied s <+> equals <+> ppr e) @@ -385,6 +386,7 @@ pprPat _ (RecP nm fs) pprPat _ (ListP ps) = brackets (commaSep ps) pprPat i (SigP p t) = parensIf (i > noPrec) $ ppr p <+> dcolon <+> ppr t pprPat _ (ViewP e p) = parens $ pprExp noPrec e <+> text "->" <+> pprPat noPrec p +pprPat _ (TypeP t) = parens $ text "type" <+> ppr t ------------------------------ instance Ppr Dec where diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs index b3b730ee83c9cbedb8db6a4d486ee17627adf53e..d9928029e0dd405a0ced3087ef3199e1ae35d79c 100644 --- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs +++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs @@ -2307,6 +2307,7 @@ data Pat | ListP [ Pat ] -- ^ @{ [1,2,3] }@ | SigP Pat Type -- ^ @{ p :: t }@ | ViewP Exp Pat -- ^ @{ e -> p }@ + | TypeP Type -- ^ @{ type p }@ deriving( Show, Eq, Ord, Data, Generic ) type FieldPat = (Name,Pat) @@ -2406,6 +2407,7 @@ data Exp | ProjectionE (NonEmpty String) -- ^ @(.x)@ or @(.x.y)@ (Record projections) | TypedBracketE Exp -- ^ @[|| e ||]@ | TypedSpliceE Exp -- ^ @$$e@ + | TypeE Type -- ^ @{ type t }@ deriving( Show, Eq, Ord, Data, Generic ) type FieldExp = (Name,Exp) diff --git a/libraries/template-haskell/changelog.md b/libraries/template-haskell/changelog.md index 3c77fc1d2f7f4f126ee940632574ed5f6a1a03a7..0efa706750fa6e457bf4baf861e0123ab332047a 100644 --- a/libraries/template-haskell/changelog.md +++ b/libraries/template-haskell/changelog.md @@ -5,6 +5,9 @@ * The kind of `Code` was changed from `forall r. (Type -> Type) -> TYPE r -> Type` to `(Type -> Type) -> forall r. TYPE r -> Type`. This enables higher-kinded usage. + * Extend `Pat` with `TypeP` and `Exp` with `TypeE`, + introduce functions `typeP` and `typeE` (GHC Proposal #281). + ## 2.21.0.0 * Record fields now belong to separate `NameSpace`s, keyed by the parent of diff --git a/testsuite/tests/dependent/should_fail/T15859.stderr b/testsuite/tests/dependent/should_fail/T15859.stderr index 30b24b1206e69dbf436232a2acf6efaff0db008c..6562200e392049b5724a1231ffdce791e0d9f8e3 100644 --- a/testsuite/tests/dependent/should_fail/T15859.stderr +++ b/testsuite/tests/dependent/should_fail/T15859.stderr @@ -2,8 +2,8 @@ T15859.hs:9:19: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall k -> k -> * - (GHC does not yet support this) • In an expression type signature: forall k -> k -> Type In the expression: (undefined :: forall k -> k -> Type) @Int In an equation for ‘a’: a = (undefined :: forall k -> k -> Type) @Int + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail1.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail1.stderr index da66f380c21a341da82f9c52fca19b229ad28261..993f19468071daed53145a39ae920a948676a286 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail1.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail1.stderr @@ -2,12 +2,12 @@ T16326_Fail1.hs:5:8: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a -> a -> a - (GHC does not yet support this) • In the type signature: id1 :: forall a -> a -> a + Suggested fix: Perhaps you intended to use RequiredTypeArguments T16326_Fail1.hs:9:8: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a -> a -> a - (GHC does not yet support this) • In the expansion of type synonym ‘Foo’ In the type signature: id2 :: Foo + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail10.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail10.stderr index 3c0ce349b97b436db5b37960f3732cc8ea51d078..bdb7eb9af09853d1cb51e7fa9a61897c30c9125e 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail10.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail10.stderr @@ -2,6 +2,6 @@ T16326_Fail10.hs:12:18: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a -> a -> a - (GHC does not yet support this) • In the type signature for ‘x’: forall a -> a -> a When checking the rewrite rule "flurmp" + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail11.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail11.stderr index f96814d281cdad1314283858273c12ac3c668e69..741598d1016fc18a5c8af21633f4ec9cc46feac6 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail11.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail11.stderr @@ -2,6 +2,6 @@ T16326_Fail11.hs:9:11: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall x -> x - (GHC does not yet support this) • When checking the class method: m :: forall a b. C a => b -> a In the class declaration for ‘C’ + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail12.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail12.stderr index 91044c0577a37f7a1772348d23121dd53a82661b..30bd04b484df768b57405a1fbd0b2d27774bab43 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail12.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail12.stderr @@ -2,7 +2,7 @@ T16326_Fail12.hs:6:1: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a -> Show a - (GHC does not yet support this) • In the context: forall a -> Show a While checking the super-classes of class ‘C’ In the class declaration for ‘C’ + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail2.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail2.stderr index 1e991a28ba2b3b340becfc52e247226f0e1cf0da..2446580ad3b3f2e886dc992cf0ab693854aa830b 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail2.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail2.stderr @@ -2,7 +2,7 @@ T16326_Fail2.hs:6:37: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a -> a -> IO () - (GHC does not yet support this) • In the type signature: blah :: forall a -> a -> IO () When checking declaration: foreign import ccall safe "blah" blah :: forall a -> a -> IO () + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail3.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail3.stderr index e7990218ecb746c15b88206c07ea2efe42904afc..4b2321d93bce90e3df03c07d5150b3549b667656 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail3.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail3.stderr @@ -2,4 +2,4 @@ T16326_Fail3.hs:6:1: error: [GHC-51580] Illegal visible, dependent quantification in the type of a term: forall a -> [a] - (GHC does not yet support this) + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail4.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail4.stderr index 5039c07f89fd99c058089ee976643935932a283c..d881bd6476dc87f9800c1f2580d28ba29c4bab56 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail4.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail4.stderr @@ -2,10 +2,10 @@ T16326_Fail4.hs:6:30: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a1 -> Maybe a1 -> Maybe a1 -> Maybe a1 - (GHC does not yet support this) • In an expression type signature: forall a -> Maybe a -> Maybe a -> Maybe a In the first argument of ‘zipWith’, namely ‘((<>) :: forall a -> Maybe a -> Maybe a -> Maybe a)’ In the expression: zipWith ((<>) :: forall a -> Maybe a -> Maybe a -> Maybe a) xs ys + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail5.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail5.stderr index ba84b8a21a0d4757f68e628fd051b83b74c22e9c..afa5830013ab454d33533fe3f77fa78aaeef0ff3 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail5.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail5.stderr @@ -2,8 +2,8 @@ T16326_Fail5.hs:7:20: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a1 -> Maybe a1 - (GHC does not yet support this) • In a pattern type signature: forall a -> Maybe a In the pattern: Nothing :: forall a -> Maybe a In an equation for ‘isJust’: isJust (Nothing :: forall a -> Maybe a) = False + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail6.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail6.stderr index 6790247a364d8011d627fe4b599f98f012c904dc..bc42133775c7ecc7183f81dcad42f6000890f397 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail6.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail6.stderr @@ -1,5 +1,4 @@ T16326_Fail6.hs:9:12: error: [GHC-51580] - Illegal visible, dependent quantification in the type of a term - (GHC does not yet support this) - In the definition of data constructor ‘MkFoo’ + • Illegal visible, dependent quantification in the type of a term + • In the definition of data constructor ‘MkFoo’ diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail8.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail8.stderr index b464931e6e04d29495aeb18e08669d20605642f5..2896c7c336f81cacc989b4ff9220216d5a15990a 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail8.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail8.stderr @@ -1,5 +1,4 @@ T16326_Fail8.hs:7:10: error: [GHC-51580] - Illegal visible, dependent quantification in the type of a term - (GHC does not yet support this) - In an instance declaration + • Illegal visible, dependent quantification in the type of a term + • In an instance declaration diff --git a/testsuite/tests/dependent/should_fail/T16326_Fail9.stderr b/testsuite/tests/dependent/should_fail/T16326_Fail9.stderr index 29afc29d93edc850e193455ce21eda027029c76b..2fcfe69e2876ca2d6a1ddc2d7ca4303d75ca92fc 100644 --- a/testsuite/tests/dependent/should_fail/T16326_Fail9.stderr +++ b/testsuite/tests/dependent/should_fail/T16326_Fail9.stderr @@ -2,7 +2,7 @@ T16326_Fail9.hs:11:5: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a -> a -> a - (GHC does not yet support this) • In the expression: lol @(forall a -> a -> a) undefined True In an equation for ‘t’: t = lol @(forall a -> a -> a) undefined True + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T17687.stderr b/testsuite/tests/dependent/should_fail/T17687.stderr index 03d9106e1dccc5a45a00d92af75821ee734ccb13..4983421a6ca595db43e1570ef27c72f2d0d6888d 100644 --- a/testsuite/tests/dependent/should_fail/T17687.stderr +++ b/testsuite/tests/dependent/should_fail/T17687.stderr @@ -2,5 +2,5 @@ T17687.hs:5:6: error: [GHC-51580] • Illegal visible, dependent quantification in the type of a term: forall a -> a -> a - (GHC does not yet support this) • In the type signature: x :: forall a -> a -> a + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/dependent/should_fail/T18271.stderr b/testsuite/tests/dependent/should_fail/T18271.stderr index 8d906b3b2d89a45f0f25ac282888eb61ff6b9dee..bd99d085b2f32076bfb8a57f7ca0302e52b8087d 100644 --- a/testsuite/tests/dependent/should_fail/T18271.stderr +++ b/testsuite/tests/dependent/should_fail/T18271.stderr @@ -1,5 +1,4 @@ T18271.hs:7:19: error: [GHC-51580] - Illegal visible, dependent quantification in the type of a term - (GHC does not yet support this) - In a deriving declaration + • Illegal visible, dependent quantification in the type of a term + • In a deriving declaration diff --git a/testsuite/tests/driver/T4437.hs b/testsuite/tests/driver/T4437.hs index 3c07aa56790d901441bc135b725b40406474a6db..8a805298f9c8e07d1e6e1235685fe3b53b7d1322 100644 --- a/testsuite/tests/driver/T4437.hs +++ b/testsuite/tests/driver/T4437.hs @@ -53,7 +53,5 @@ expectedCabalOnlyExtensions = ["Generics", "Unsafe", "Trustworthy", "MonadFailDesugaring", - "MonoPatBinds", - -- https://github.com/haskell/cabal/pull/8521 - "RequiredTypeArguments" + "MonoPatBinds" ] diff --git a/testsuite/tests/hiefile/should_run/HieVdq.hs b/testsuite/tests/hiefile/should_run/HieVdq.hs new file mode 100644 index 0000000000000000000000000000000000000000..f02d2bd01db58fba99b3daca885e5629fe4dbefb --- /dev/null +++ b/testsuite/tests/hiefile/should_run/HieVdq.hs @@ -0,0 +1,34 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module Main where + +import GHC.Types.Name (nameSrcSpan) +import TestUtils +import qualified Data.Map as M +import Data.Foldable +import Data.Either + +f :: forall a -> a -> Maybe a +f (type t) (x :: t) = Just (x :: t) +-- ^p1 ^p2 ^p3 + +p1,p2 :: (Int,Int) +p1 = (13,9) +p2 = (13,18) +p3 = (13,34) + +selectPoint' :: HieFile -> (Int,Int) -> HieAST Int +selectPoint' hf loc = + maybe (error "point not found") id $ selectPoint hf loc + +main = do + (df, hf) <- readTestHie "HieVdq.hie" + forM_ [p1,p2,p3] $ \point -> do + putStr $ "At " ++ show point ++ ", got names: " + let names = + concatMap (rights . M.keys . nodeIdentifiers) $ + M.elems $ getSourcedNodeInfo $ + sourcedNodeInfo $ selectPoint' hf point + forM_ names $ \name -> do + putStrLn (render df (nameSrcSpan name, name)) diff --git a/testsuite/tests/hiefile/should_run/HieVdq.stdout b/testsuite/tests/hiefile/should_run/HieVdq.stdout new file mode 100644 index 0000000000000000000000000000000000000000..edfc21d527f0fe42083ab59452ab99dba01f0a06 --- /dev/null +++ b/testsuite/tests/hiefile/should_run/HieVdq.stdout @@ -0,0 +1,3 @@ +At (13,9), got names: (HieVdq.hs:13:9, t) +At (13,18), got names: (HieVdq.hs:13:9, t) +At (13,34), got names: (HieVdq.hs:13:9, t) diff --git a/testsuite/tests/hiefile/should_run/all.T b/testsuite/tests/hiefile/should_run/all.T index 2fc72443cc65326372ebaed0f96a8acfa6d02741..2628adb2ad311f1bc1287057b1c347a5d95f0bb1 100644 --- a/testsuite/tests/hiefile/should_run/all.T +++ b/testsuite/tests/hiefile/should_run/all.T @@ -4,3 +4,4 @@ test('T20341', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUti test('T23492', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('RecordDotTypes', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('SpliceTypes', [req_th, extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) +test('HieVdq', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) diff --git a/testsuite/tests/vdq-rta/should_compile/Makefile b/testsuite/tests/vdq-rta/should_compile/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bced01ff9b62f2c19d86ae87e96035574fca2c4a --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/Makefile @@ -0,0 +1,3 @@ +TOP=../../.. +include $(TOP)/mk/boilerplate.mk +include $(TOP)/mk/test.mk \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T14158_vdq.hs b/testsuite/tests/vdq-rta/should_compile/T14158_vdq.hs new file mode 100644 index 0000000000000000000000000000000000000000..2cb043a6901a84e5439102124672d4aa4e7b6a28 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T14158_vdq.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T14158_vdq where + +import Data.Kind +import qualified Control.Category as Cat + +civ :: + forall {k}. + forall (cat :: k -> k -> Type) -> + forall (a :: k). + Cat.Category cat => + cat a a +civ (type cat) = Cat.id @cat + +f = (civ (type (->)) >>=) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T17792_vdq.hs b/testsuite/tests/vdq-rta/should_compile/T17792_vdq.hs new file mode 100644 index 0000000000000000000000000000000000000000..ac5e8f8520c9655e36cee7257447c59219a7247a --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T17792_vdq.hs @@ -0,0 +1,18 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# OPTIONS_GHC -fdefer-type-errors #-} + +module T17792_vdq where + +class C a where + m :: a + +-- Check that instantiating an out-of-scope identifier with a +-- required type argument in a class instance and with deferred +-- type errors does not lead to a panic. +-- +-- This problem was observed with TypeApplications in #17792. +-- Here we check that RequiredTypeArguments, a somewhat related +-- feature, is not affected. +instance C Bool where + m = notInScope (type Word) diff --git a/testsuite/tests/vdq-rta/should_compile/T17792_vdq.stderr b/testsuite/tests/vdq-rta/should_compile/T17792_vdq.stderr new file mode 100644 index 0000000000000000000000000000000000000000..7678b29c906e5e92eb8debeb702e8d067cf31308 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T17792_vdq.stderr @@ -0,0 +1,3 @@ + +T17792_vdq.hs:18:7: warning: [GHC-88464] [-Wdeferred-out-of-scope-variables (in -Wdefault)] + Variable not in scope: notInScope :: Bool diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_callStack.hs b/testsuite/tests/vdq-rta/should_compile/T22326_callStack.hs new file mode 100644 index 0000000000000000000000000000000000000000..dc2730e25e268b2721ddd74e9bb8647a67135023 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_callStack.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_callStack where + +import Data.Kind (Type) +import GHC.Stack + +f :: forall (a :: Type) -> CallStack +f (type _) = callStack \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_idv.hs b/testsuite/tests/vdq-rta/should_compile/T22326_idv.hs new file mode 100644 index 0000000000000000000000000000000000000000..b6372039b4a57049a1536e52b2bc2159b0c977f1 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_idv.hs @@ -0,0 +1,41 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE TypeApplications #-} + +module T22326_idv where + +-- Definition: +idv :: forall a -> a -> a +idv (type t) x = x :: t + +-- Usage: +rInt = idv (type Int) 42 +rDouble = idv (type Double) 42 +rBool = idv (type Bool) True +rChar = idv (type Char) 'x' +rList = idv (type [Int]) [1,2,3] +rTup = idv (type (Int,Bool)) (0,False) + +-- Definition (using a lambda) +idv_lam :: forall a -> a -> a +idv_lam = \(type t) x -> x :: t + +-- Definition (eta-reduced) +idv_eta :: forall a -> a -> a +idv_eta = idv + +-- Definition (using vta on the rhs) +idv_vta :: forall a -> a -> a +idv_vta (type t) = id @t + +-- Definition (using sig on the rhs) +idv_sig :: forall a -> a -> a +idv_sig (type t) = id :: t -> t + +-- Definition (using a wildcard) +idv_wild :: forall a -> a -> a +idv_wild (type _) x = x + +-- Usage (using a wildcard) +rBool' = idv (type _) True +rChar' = idv (type _) 'x' \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_noext.hs b/testsuite/tests/vdq-rta/should_compile/T22326_noext.hs new file mode 100644 index 0000000000000000000000000000000000000000..02088fac3cf71b82a9dc21c96007737268547d61 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_noext.hs @@ -0,0 +1,13 @@ +{-# LANGUAGE NoRequiredTypeArguments #-} -- VDQ/RTA is disabled +{-# LANGUAGE ExplicitNamespaces #-} + +module T22326_noext where + +import T22326_noext_def + +-- The calls to id_vdq are accepted, even though RequiredTypeArguments are +-- disabled in this module. +-- +-- The extension is only required at definition site, not at use sites. +-- +s = id_vdq (type String) "Hello" \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_noext_def.hs b/testsuite/tests/vdq-rta/should_compile/T22326_noext_def.hs new file mode 100644 index 0000000000000000000000000000000000000000..b571298f410fae6b0a0c352a926fd630ba4dd6ae --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_noext_def.hs @@ -0,0 +1,10 @@ +-- Helper module for use in T22326_noext. +-- Defines id_vdq. + +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_noext_def (id_vdq) where + +id_vdq :: forall a -> a -> a +id_vdq = \(type _) -> id \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_sig.hs b/testsuite/tests/vdq-rta/should_compile/T22326_sig.hs new file mode 100644 index 0000000000000000000000000000000000000000..17b3a96e7ec1caf66d4cfc020093007a3313378f --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_sig.hs @@ -0,0 +1,45 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeFamilies #-} + +module T22326_sig where + +import Data.Kind +import Data.Type.Bool +import Data.Proxy + +data SBool b where + SFalse :: SBool False + STrue :: SBool True + +class KnownBool b where + boolSing :: SBool b + +boolVal :: forall b -> KnownBool b => Bool +boolVal (type b) = + case boolSing @b of + SFalse -> False + STrue -> True + +f :: forall x -> x -> () +f (type (x :: Type)) x = () + +g :: forall b -> KnownBool b => If b Integer String +g (type (b :: Bool)) = + case boolSing @b of + SFalse -> "Hello" + STrue -> 42 + +type FromJust :: Maybe a -> a +type family FromJust m where + FromJust (Just x) = x + +type KindOf :: k -> Type +type KindOf (a :: k) = k + +h :: forall m -> Proxy (KindOf (FromJust m)) +h (type (m :: Maybe a)) = Proxy @a + +hBool :: Proxy Bool +hBool = h (type (Just True)) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_sizeOf.hs b/testsuite/tests/vdq-rta/should_compile/T22326_sizeOf.hs new file mode 100644 index 0000000000000000000000000000000000000000..ee55357b105f6f5733a4da74f2c9ca5eef1e27e5 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_sizeOf.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_sizeOf where + +import Foreign.Storable + +-- Definition: +sizeOfVis :: forall a -> Storable a => Int +sizeOfVis (type t) = sizeOf (undefined :: t) + +-- Usage: +sInt = sizeOfVis (type Int) +sDouble = sizeOfVis (type Double) +sBool = sizeOfVis (type Bool) +sChar = sizeOfVis (type Char) +sUnit = sizeOfVis (type ()) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_symbolVal.hs b/testsuite/tests/vdq-rta/should_compile/T22326_symbolVal.hs new file mode 100644 index 0000000000000000000000000000000000000000..3061dbc3678a1f3b551dccfa69e780818f7a5335 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_symbolVal.hs @@ -0,0 +1,81 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableSuperClasses #-} +{-# LANGUAGE UndecidableInstances #-} + +module T22326_symbolVal where + +import Data.Kind +import Data.Proxy +import GHC.TypeLits + +-- Definition: +symbolValVis :: forall s -> KnownSymbol s => String +symbolValVis (type s) = symbolVal (Proxy :: Proxy s) + +-- Usage: +strHelloWorld = symbolValVis (type ("Hello, " `AppendSymbol` "World")) + +-- Operator taking a term-level argument before a required type argument: +(++.) :: String -> forall (s :: Symbol) -> KnownSymbol s => String +s1 ++. (type s2) = s1 ++ symbolValVis (type s2) +infixr 5 ++. + +strTmPlusTy = "Tm" ++ "+" ++. (type "Ty") + +------------------------------------------------- +-- Required type arguments in class methods -- +-- and in higher-rank positions -- +------------------------------------------------- + +-- Continuation-passing encoding of a list spine: +-- +-- data Spine xs where +-- Cons :: Spine xs -> Spine (x : xs) +-- Nil :: Spine '[] +-- +type WithSpine :: [k] -> Constraint +class WithSpine xs where + onSpine :: + forall r. + forall xs' -> (xs' ~ xs) => -- workaround b/c it's not possible to make xs visible + ((xs ~ '[]) => r) -> + (forall y ys -> (xs ~ (y : ys)) => WithSpine ys => r) -> + r + +instance WithSpine '[] where + onSpine (type xs) onNil _ = onNil + +instance forall x xs. WithSpine xs => WithSpine (x : xs) where + onSpine (type xs') _ onCons = onCons (type x) (type xs) + +type All :: (k -> Constraint) -> [k] -> Constraint +type family All c xs where + All c '[] = () + All c (a : as) = (c a, All c as) + +type KnownSymbols :: [Symbol] -> Constraint +class All KnownSymbol ss => KnownSymbols ss +instance All KnownSymbol ss => KnownSymbols ss + +symbolVals :: forall ss -> (KnownSymbols ss, WithSpine ss) => [String] +symbolVals (type ss) = + onSpine (type ss) [] $ \(type s) (type ss') -> + symbolValVis (type s) : symbolVals (type ss') + +-- Reify a type-level list of strings at the term level. +strsLoremIpsum = symbolVals (type ["lorem", "ipsum", "dolor", "sit", "amet"]) + +-- Pass a required type argument to a continuation: +withSymbolVis :: String -> (forall s -> KnownSymbol s => r) -> r +withSymbolVis str cont = + case someSymbolVal str of + SomeSymbol (Proxy :: Proxy s) -> cont (type s) + +-- Use a required type argument in a continuation: +strLengthViaSymbol :: String -> Int +strLengthViaSymbol str = + withSymbolVis str $ \(type s) -> + length (symbolValVis (type s)) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_th_dump1.hs b/testsuite/tests/vdq-rta/should_compile/T22326_th_dump1.hs new file mode 100644 index 0000000000000000000000000000000000000000..08eaf6cf8c8b38c4e50938f3eaeed060b921b1a7 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_th_dump1.hs @@ -0,0 +1,13 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE TemplateHaskell #-} + +module T22326_th_dump1 where + +$([d| f :: Integer -> forall a -> Num a => a + f n (type t) = fromInteger n :: t + |]) + +$([d| x = 42 `f` (type Double) + n = f 42 (type Integer) + |]) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_th_dump1.stderr b/testsuite/tests/vdq-rta/should_compile/T22326_th_dump1.stderr new file mode 100644 index 0000000000000000000000000000000000000000..8158fcd8d3abddb9d6de8e7447ce86d69b3c74d9 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_th_dump1.stderr @@ -0,0 +1,12 @@ +T22326_th_dump1.hs:(7,2)-(9,7): Splicing declarations + [d| f :: Integer -> forall a -> Num a => a + f n (type t) = fromInteger n :: t |] + ======> + f :: Integer -> forall a -> Num a => a + f n (type t) = fromInteger n :: t +T22326_th_dump1.hs:(11,2)-(13,7): Splicing declarations + [d| x = 42 `f` (type Double) + n = f 42 (type Integer) |] + ======> + x = (42 `f` (type Double)) + n = f 42 (type Integer) diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_th_pprint1.hs b/testsuite/tests/vdq-rta/should_compile/T22326_th_pprint1.hs new file mode 100644 index 0000000000000000000000000000000000000000..69279a6a888da5d144c1be8f49d8421163e94840 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_th_pprint1.hs @@ -0,0 +1,21 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE TemplateHaskell #-} + +module T22326_th_pprint1 where + +import System.IO +import Language.Haskell.TH + +do decls <- + [d| + -- Definition: + f :: Integer -> forall a -> Num a => a + f n (type _) = fromInteger n + + -- Usage: + x = 42 `f` (type Double) + n = f 42 (type Integer) + |] + runIO $ hPutStrLn stderr $ pprint decls + return [] diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_th_pprint1.stderr b/testsuite/tests/vdq-rta/should_compile/T22326_th_pprint1.stderr new file mode 100644 index 0000000000000000000000000000000000000000..5bb1b6da12a4d60dde6d26eb32989a1361c588a6 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_th_pprint1.stderr @@ -0,0 +1,5 @@ +f_0 :: GHC.Num.Integer.Integer -> + forall a_1 -> GHC.Num.Num a_1 => a_1 +f_0 n_2 (type _) = GHC.Num.fromInteger n_2 +x_3 = 42 `f_0` (type GHC.Types.Double) +n_4 = f_0 42 (type GHC.Num.Integer.Integer) diff --git a/testsuite/tests/vdq-rta/should_compile/T22326_typeRep.hs b/testsuite/tests/vdq-rta/should_compile/T22326_typeRep.hs new file mode 100644 index 0000000000000000000000000000000000000000..3c00a55901b87a8f2114b92ee3793af295a2a8f9 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/T22326_typeRep.hs @@ -0,0 +1,40 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE DataKinds #-} + +module T22326_typeRep where + +import Type.Reflection +import Data.Kind +import GHC.TypeLits + +-- Definition: +typeRepVis :: forall a -> Typeable a => TypeRep a +typeRepVis (type t) = typeRep @t + +-- Usage: +tMaybe = typeRepVis (type Maybe) +tMaybeString = typeRepVis (type (Maybe String)) +tFunctor = typeRepVis (type Functor) +tHello = typeRepVis (type "Hello") +tTupFun = typeRepVis (type ((Int,Bool,Char) -> Double)) + +-- Definition (using a lambda) +typeRepVis_lam :: forall a -> Typeable a => TypeRep a +typeRepVis_lam = \(type t) -> typeRep @t + +-- Definition (with explicit kind quantification) +typeRepVis_kforall :: forall k. forall (a :: k) -> Typeable a => TypeRep a +typeRepVis_kforall = typeRepVis + +-- Definition (with required kind parameter): +typeRepKiVis :: forall k (a :: k) -> Typeable a => TypeRep a +typeRepKiVis (type k) (type a) = typeRep @(a :: k) + +-- Usage (with required kind parameter): +tMaybe' = typeRepKiVis (type (Type -> Type)) (type Maybe) +tMaybeString' = typeRepKiVis (type Type) (type (Maybe String)) +tFunctor' = typeRepKiVis (type ((Type -> Type) -> Constraint)) (type Functor) +tHello' = typeRepKiVis (type Symbol) (type "Hello") +tTupFun' = typeRepKiVis (type Type) (type ((Int,Bool,Char) -> Double)) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_compile/WithSpineVDQ_LintErr.hs b/testsuite/tests/vdq-rta/should_compile/WithSpineVDQ_LintErr.hs new file mode 100644 index 0000000000000000000000000000000000000000..d154f1280a132881a22f0c70699bc8055d3156dc --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/WithSpineVDQ_LintErr.hs @@ -0,0 +1,29 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE DataKinds #-} + +module WithSpineVDQ_LintErr (uSSZ) where + +import Data.Kind + +data Peano = Z | S Peano + +type WithSpine :: Peano -> Constraint +class WithSpine n where + -- Single-method class (newtype dict) + onSpine :: + forall n' -> (n' ~ n) => -- workaround b/c it's not possible to make `n` visible + (forall m -> (n ~ S m) => WithSpine m => ()) -> + () + +instance WithSpine Z where + onSpine (type n) _ = () + +instance forall m. WithSpine m => WithSpine (S m) where + onSpine (type n) f = f (type m) + +getUnit :: forall n -> WithSpine n => () +getUnit (type n) = onSpine (type n) (\(type n') -> getUnit (type n')) + +-- uSSZ :: () +uSSZ = getUnit (type (S (S Z))) diff --git a/testsuite/tests/vdq-rta/should_compile/all.T b/testsuite/tests/vdq-rta/should_compile/all.T new file mode 100644 index 0000000000000000000000000000000000000000..598048af1987fd845ab44a4ddefe1d4d3e06627a --- /dev/null +++ b/testsuite/tests/vdq-rta/should_compile/all.T @@ -0,0 +1,15 @@ +setTestOpts(normalise_version('base','ghc-prim')) + +test('T22326_idv', normal, compile, ['']) +test('T22326_typeRep', normal, compile, ['']) +test('T22326_sizeOf', normal, compile, ['']) +test('T22326_symbolVal', normal, compile, ['']) +test('T22326_noext', extra_files(['T22326_noext_def.hs']), multimod_compile, ['T22326_noext', '-v0']) +test('T22326_callStack', normal, compile, ['']) +test('T22326_sig', normal, compile, ['']) +test('T17792_vdq', normal, compile, ['']) +test('T14158_vdq', normal, compile, ['']) +test('WithSpineVDQ_LintErr', normal, compile, ['']) + +test('T22326_th_dump1', req_th, compile, ['-v0 -ddump-splices -dsuppress-uniques']) +test('T22326_th_pprint1', req_th, compile, ['']) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/Makefile b/testsuite/tests/vdq-rta/should_fail/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..bced01ff9b62f2c19d86ae87e96035574fca2c4a --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/Makefile @@ -0,0 +1,3 @@ +TOP=../../.. +include $(TOP)/mk/boilerplate.mk +include $(TOP)/mk/test.mk \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_ado.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ado.hs new file mode 100644 index 0000000000000000000000000000000000000000..8f1dc3493840d7e8a6062544951bfa9fd2d89862 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ado.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE ApplicativeDo #-} + +module T22326_fail_ado where + +m :: IO () +m = do + type a <- undefined + pure () \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_ado.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ado.stderr new file mode 100644 index 0000000000000000000000000000000000000000..64a0c19b67bcc48deac19d7a536dbfee0cf615dc --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ado.stderr @@ -0,0 +1,9 @@ + +T22326_fail_ado.hs:9:3: error: [GHC-70206] + • Illegal type pattern. + A type pattern must be checked against a visible forall. + • In the pattern: type a + In a stmt of a 'do' block: type a <- undefined + In the expression: + do type a <- undefined + return () diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_app.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_app.hs new file mode 100644 index 0000000000000000000000000000000000000000..b2de7829662f90f79b0b42841b0227467b026288 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_app.hs @@ -0,0 +1,7 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_app where + +xhead = (type Maybe) undefined +xarg = undefined (type Int) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_app.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_app.stderr new file mode 100644 index 0000000000000000000000000000000000000000..137f47df7b29f81ca63c780fbde1f9d4809decf2 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_app.stderr @@ -0,0 +1,13 @@ + +T22326_fail_app.hs:6:10: error: [GHC-35499] + • Illegal type expression. + A type expression must be used to instantiate a visible forall. + • In the expression: (type Maybe) undefined + In an equation for ‘xhead’: xhead = (type Maybe) undefined + +T22326_fail_app.hs:7:20: error: [GHC-35499] + • Illegal type expression. + A type expression must be used to instantiate a visible forall. + • In the first argument of ‘undefined’, namely ‘(type Int)’ + In the expression: undefined (type Int) + In an equation for ‘xarg’: xarg = undefined (type Int) diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_caseof.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_caseof.hs new file mode 100644 index 0000000000000000000000000000000000000000..f1a0127b8b301fa4180ed2d874dc0c7f950a41f4 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_caseof.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_caseof where + +f :: Int -> Bool +f x = + case x of + (type _) -> True + _ -> False \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_caseof.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_caseof.stderr new file mode 100644 index 0000000000000000000000000000000000000000..63315bc2e09b3848a1d2bbb1e4257a83b5e04f73 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_caseof.stderr @@ -0,0 +1,10 @@ + +T22326_fail_caseof.hs:9:6: error: [GHC-70206] + • Illegal type pattern. + A type pattern must be checked against a visible forall. + • In the pattern: type _ + In a case alternative: (type _) -> True + In the expression: + case x of + (type _) -> True + _ -> False diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext1.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext1.hs new file mode 100644 index 0000000000000000000000000000000000000000..444d4b5187d25cb87d9f817603e63b394a8d825a --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext1.hs @@ -0,0 +1,12 @@ +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE NoExplicitNamespaces #-} + +module T22326_fail_ext1 where + +-- Using the (type ...) syntax requires the ExplicitNamespaces extension, +-- which is disabled in this module. +-- +-- This is not related to whether the RequiredTypeArguments extension is +-- enabled, as Part 2 of the proposal (https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0281-visible-forall.rst) +-- shows how the feature could be used without the ‘type’ keyword. +x = undefined (type Int) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext1.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext1.stderr new file mode 100644 index 0000000000000000000000000000000000000000..fed2bb02f328d1ccbc64a0c79b8df9cb73165543 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext1.stderr @@ -0,0 +1,4 @@ + +T22326_fail_ext1.hs:12:16: error: [GHC-47007] + Illegal keyword 'type' + Suggested fix: Perhaps you intended to use ExplicitNamespaces diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext2.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext2.hs new file mode 100644 index 0000000000000000000000000000000000000000..391e9b516ec3898e911a17367b2f03877dabe219 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext2.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE NoRequiredTypeArguments #-} + +module T22326_fail_ext2 where + +-- Using visible forall in the type of a term is only possible +-- with the RequiredTypeArguments extension, which is disabled +-- in this module. +f :: forall x -> () +f = f \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext2.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext2.stderr new file mode 100644 index 0000000000000000000000000000000000000000..a3a1996981430e5573e71edc0542a6c5a9cf4ead --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_ext2.stderr @@ -0,0 +1,6 @@ + +T22326_fail_ext2.hs:8:6: error: [GHC-51580] + • Illegal visible, dependent quantification in the type of a term: + forall {k}. forall (x :: k) -> () + • In the type signature: f :: forall x -> () + Suggested fix: Perhaps you intended to use RequiredTypeArguments diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_match.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_match.hs new file mode 100644 index 0000000000000000000000000000000000000000..64120ddd62e62dd8e9a0873e4de0b7404400ae42 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_match.hs @@ -0,0 +1,7 @@ +{-# LANGUAGE RequiredTypeArguments #-} +{-# LANGUAGE ExplicitNamespaces #-} + +module T22326_fail_match where + +f :: forall t -> t -> () +f (type (Maybe a)) x = () \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_match.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_match.stderr new file mode 100644 index 0000000000000000000000000000000000000000..591855176fe711a985c36abc2c927dac05af13b0 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_match.stderr @@ -0,0 +1,9 @@ + +T22326_fail_match.hs:7:4: error: [GHC-25897] + • Couldn't match expected type ‘t’ with actual type ‘Maybe a’ + ‘t’ is a rigid type variable bound by + a type expected by the context: + forall t -> t -> () + at T22326_fail_match.hs:7:1-25 + • In the pattern: type (Maybe a) + In an equation for ‘f’: f (type (Maybe a)) x = () diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_n_args.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_n_args.hs new file mode 100644 index 0000000000000000000000000000000000000000..ba0f7a468a39901d3c61ce39087b6212605bf04b --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_n_args.hs @@ -0,0 +1,6 @@ +{-# LANGUAGE RequiredTypeArguments, ExplicitNamespaces #-} + +module T22326_fail_n_args where + +f :: a -> forall b -> b +f x (type y) z = undefined \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_n_args.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_n_args.stderr new file mode 100644 index 0000000000000000000000000000000000000000..b313b93601b612c0bb0b8c96e0a0a5f02f00e724 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_n_args.stderr @@ -0,0 +1,9 @@ + +T22326_fail_n_args.hs:6:1: error: [GHC-25897] + • Couldn't match expected type ‘b’ with actual type ‘p0 -> a0’ + ‘b’ is a rigid type variable bound by + a type expected by the context: + forall b -> b + at T22326_fail_n_args.hs:6:1-26 + • The equation for ‘f’ has three value arguments, + but its type ‘a -> forall b -> b’ has only two diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_nonlinear.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_nonlinear.hs new file mode 100644 index 0000000000000000000000000000000000000000..ce9f13cc96992438a31dfa43eda25d43364082af --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_nonlinear.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_nonlinear where + +import Data.Kind (Type) + +f :: forall (a :: Type) (b :: Type) -> () +f (type t) (type t) = () \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_nonlinear.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_nonlinear.stderr new file mode 100644 index 0000000000000000000000000000000000000000..513315502b6b99f8e0c8d265667c5630ee9e5529 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_nonlinear.stderr @@ -0,0 +1,6 @@ + +T22326_fail_nonlinear.hs:9:9: error: [GHC-10498] + • Conflicting definitions for ‘t’ + Bound at: T22326_fail_nonlinear.hs:9:9 + T22326_fail_nonlinear.hs:9:18 + • In an equation for ‘f’ diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_notInScope.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_notInScope.hs new file mode 100644 index 0000000000000000000000000000000000000000..a4a882cbfbe3b022f6154a36983569a9fd959d20 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_notInScope.hs @@ -0,0 +1,6 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_notInScope where + +x = notInScope (type Int) diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_notInScope.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_notInScope.stderr new file mode 100644 index 0000000000000000000000000000000000000000..242fa221ffc88a9d0e9f4b9ccb0e6bfa0cf302cc --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_notInScope.stderr @@ -0,0 +1,3 @@ + +T22326_fail_notInScope.hs:6:5: error: [GHC-88464] + Variable not in scope: notInScope diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_pat.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_pat.hs new file mode 100644 index 0000000000000000000000000000000000000000..c1625451362b60a64c1ff291dd079ba52042d9b5 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_pat.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_pat where + +import Data.Kind (Type) + +f :: forall (a :: Type) -> () +f (type Int) = () \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_pat.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_pat.stderr new file mode 100644 index 0000000000000000000000000000000000000000..49deefd8211f03f3592fcb1ad55ef95914e85615 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_pat.stderr @@ -0,0 +1,9 @@ + +T22326_fail_pat.hs:9:4: error: [GHC-25897] + • Couldn't match expected type ‘a’ with actual type ‘Int’ + ‘a’ is a rigid type variable bound by + a type expected by the context: + forall a -> () + at T22326_fail_pat.hs:9:1-17 + • In the pattern: type Int + In an equation for ‘f’: f (type Int) = () diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_patsyn.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_patsyn.hs new file mode 100644 index 0000000000000000000000000000000000000000..89593ccec14a1a50c92a1430ed081bef72682a5f --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_patsyn.hs @@ -0,0 +1,6 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE PatternSynonyms #-} + +module T22326_fail_patsyn where + +pattern MyPat = type Int \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_patsyn.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_patsyn.stderr new file mode 100644 index 0000000000000000000000000000000000000000..fef46bb00a2f1e04758eedd0d3a157357a92bd1b --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_patsyn.stderr @@ -0,0 +1,6 @@ + +T22326_fail_patsyn.hs:6:17: error: [GHC-70206] + • Illegal type pattern. + A type pattern must be checked against a visible forall. + • In the pattern: type Int + In the declaration for pattern synonym ‘MyPat’ diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_arg.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_arg.hs new file mode 100644 index 0000000000000000000000000000000000000000..519194599c63692882b6d71a2e132aa590b9aa26 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_arg.hs @@ -0,0 +1,9 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_raw_arg where + +f :: forall (a :: k) -> () +f (type _) = () + +x = f (\_ -> _) \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_arg.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_arg.stderr new file mode 100644 index 0000000000000000000000000000000000000000..ffc0940a9808d1f5df68eedd077cdba93d91f7d2 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_arg.stderr @@ -0,0 +1,6 @@ + +T22326_fail_raw_arg.hs:9:5: error: [GHC-29092] + • Ill-formed type argument: \ _ -> _ + Expected a type expression introduced with the ‘type’ keyword. + • In the expression: f (\ _ -> _) + In an equation for ‘x’: x = f (\ _ -> _) diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_pat.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_pat.hs new file mode 100644 index 0000000000000000000000000000000000000000..2b8ca18a2eafa83e0fa6b0efe88973a4c812fad4 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_pat.hs @@ -0,0 +1,7 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_raw_pat where + +f :: forall (a :: k) -> () +f x = () \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_pat.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_pat.stderr new file mode 100644 index 0000000000000000000000000000000000000000..cae79feb09f417c1187c92fc2dd51c3dacb0021c --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_raw_pat.stderr @@ -0,0 +1,5 @@ + +T22326_fail_raw_pat.hs:7:3: error: [GHC-88754] + • Ill-formed type pattern: x + Expected a type pattern introduced with the ‘type’ keyword. + • In an equation for ‘f’: f x = () diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_top.hs b/testsuite/tests/vdq-rta/should_fail/T22326_fail_top.hs new file mode 100644 index 0000000000000000000000000000000000000000..a2701fe7c334fb4fbffb8e7894c8f95266892308 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_top.hs @@ -0,0 +1,6 @@ +{-# LANGUAGE ExplicitNamespaces #-} +{-# LANGUAGE RequiredTypeArguments #-} + +module T22326_fail_top where + +xtop = type Int \ No newline at end of file diff --git a/testsuite/tests/vdq-rta/should_fail/T22326_fail_top.stderr b/testsuite/tests/vdq-rta/should_fail/T22326_fail_top.stderr new file mode 100644 index 0000000000000000000000000000000000000000..0dfd5a144f63d6ca534d17f4b18b4249bead67e3 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/T22326_fail_top.stderr @@ -0,0 +1,6 @@ + +T22326_fail_top.hs:6:9: error: [GHC-35499] + • Illegal type expression. + A type expression must be used to instantiate a visible forall. + • In the expression: type Int + In an equation for ‘xtop’: xtop = type Int diff --git a/testsuite/tests/vdq-rta/should_fail/all.T b/testsuite/tests/vdq-rta/should_fail/all.T new file mode 100644 index 0000000000000000000000000000000000000000..2dee99b6e8acac0515dda7190ce05713e9024e31 --- /dev/null +++ b/testsuite/tests/vdq-rta/should_fail/all.T @@ -0,0 +1,14 @@ +test('T22326_fail_ext1', normal, compile_fail, ['']) +test('T22326_fail_ext2', normal, compile_fail, ['']) +test('T22326_fail_top', normal, compile_fail, ['']) +test('T22326_fail_app', normal, compile_fail, ['']) +test('T22326_fail_notInScope', normal, compile_fail, ['']) +test('T22326_fail_raw_pat', normal, compile_fail, ['']) +test('T22326_fail_raw_arg', normal, compile_fail, ['']) +test('T22326_fail_pat', normal, compile_fail, ['']) +test('T22326_fail_nonlinear', normal, compile_fail, ['']) +test('T22326_fail_caseof', normal, compile_fail, ['']) +test('T22326_fail_ado', normal, compile_fail, ['']) +test('T22326_fail_n_args', normal, compile_fail, ['']) +test('T22326_fail_patsyn', normal, compile_fail, ['']) +test('T22326_fail_match', normal, compile_fail, ['']) \ No newline at end of file diff --git a/utils/check-exact/ExactPrint.hs b/utils/check-exact/ExactPrint.hs index 3bf8b77be296534ba5c02d014d86a51a5dae8299..1eaa26853e410c8fc88a614b2a53b57e9d51375a 100644 --- a/utils/check-exact/ExactPrint.hs +++ b/utils/check-exact/ExactPrint.hs @@ -2656,6 +2656,7 @@ instance ExactPrint (HsExpr GhcPs) where getAnnotationEntry (HsProc an _ _) = fromAnn an getAnnotationEntry (HsStatic an _) = fromAnn an getAnnotationEntry (HsPragE{}) = NoEntryVal + getAnnotationEntry (HsEmbTy{}) = NoEntryVal setAnnotationAnchor a@(HsVar{}) _ _s = a setAnnotationAnchor (HsUnboundVar an a) anc cs = (HsUnboundVar (setAnchorEpa an anc cs) a) @@ -2694,6 +2695,7 @@ instance ExactPrint (HsExpr GhcPs) where setAnnotationAnchor (HsProc an a b) anc cs = (HsProc (setAnchorEpa an anc cs) a b) setAnnotationAnchor (HsStatic an a) anc cs = (HsStatic (setAnchorEpa an anc cs) a) setAnnotationAnchor a@(HsPragE{}) _ _s = a + setAnnotationAnchor a@(HsEmbTy{}) _ _s = a exact (HsVar x n) = do n' <- markAnnotated n @@ -4559,6 +4561,7 @@ instance ExactPrint (Pat GhcPs) where getAnnotationEntry (NPat an _ _ _) = fromAnn an getAnnotationEntry (NPlusKPat an _ _ _ _ _) = fromAnn an getAnnotationEntry (SigPat an _ _) = fromAnn an + getAnnotationEntry (EmbTyPat _ _ _) = NoEntryVal setAnnotationAnchor a@(WildPat _) _ _s = a setAnnotationAnchor a@(VarPat _ _) _ _s = a @@ -4576,6 +4579,7 @@ instance ExactPrint (Pat GhcPs) where setAnnotationAnchor (NPat an a b c) anc cs = (NPat (setAnchorEpa an anc cs) a b c) setAnnotationAnchor (NPlusKPat an a b c d e) anc cs = (NPlusKPat (setAnchorEpa an anc cs) a b c d e) setAnnotationAnchor (SigPat an a b) anc cs = (SigPat (setAnchorEpa an anc cs) a b) + setAnnotationAnchor a@(EmbTyPat _ _ _) _ _s = a exact (WildPat w) = do anchor <- getAnchorU @@ -4665,6 +4669,11 @@ instance ExactPrint (Pat GhcPs) where sig' <- markAnnotated sig return (SigPat an0 pat' sig') + exact (EmbTyPat x toktype tp) = do + toktype' <- markToken toktype + tp' <- markAnnotated tp + return (EmbTyPat x toktype' tp') + -- --------------------------------------------------------------------- instance ExactPrint (HsPatSigType GhcPs) where