diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2017-11-28 11:33:37 +0000 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2017-12-07 14:40:35 +0000 |
commit | fa29df02a1b0b926afb2525a258172dcbf0ea460 (patch) | |
tree | 594244e6f84a99a36acfd962eeb62b4a35f42726 /compiler/rename/RnSource.hs | |
parent | 5f332e1dab000e1f79c127d441f618280d14d2bd (diff) | |
download | haskell-fa29df02a1b0b926afb2525a258172dcbf0ea460.tar.gz |
Refactor ConDecl: Trac #14529
This patch refactors HsDecls.ConDecl. Specifically
* ConDeclGADT was horrible, with all the information hidden
inside con_res_ty. Now it's kept separate, as it should be.
* ConDeclH98: use [LHsTyVarBndr] instead of LHsQTyVars for the
existentials. There is no implicit binding here.
* Add a field con_forall to both ConDeclGADT and ConDeclH98
which says if there is an explicit user-written forall.
* Field renamings in ConDecl
con_cxt to con_mb_cxt
con_details to con_args
There is an accompanying submodule update to Haddock.
Also the following change turned out to remove a lot of clutter:
* add a smart constructor for HsAppsTy, namely mkHsAppsTy,
and use it consistently. This avoids a lot of painful pattern
matching for the common singleton case.
Two api-annotation tests (T10278, and T10399) are broken, hence marking
them as expect_broken(14529). Alan is going to fix them, probably by
changing the con_forall field to
con_forall :: Maybe SrcSpan
instead of Bool
Diffstat (limited to 'compiler/rename/RnSource.hs')
-rw-r--r-- | compiler/rename/RnSource.hs | 116 |
1 files changed, 77 insertions, 39 deletions
diff --git a/compiler/rename/RnSource.hs b/compiler/rename/RnSource.hs index c0347c4d6b..897e660515 100644 --- a/compiler/rename/RnSource.hs +++ b/compiler/rename/RnSource.hs @@ -52,7 +52,6 @@ import Avail import Outputable import Bag import BasicTypes ( DerivStrategy, RuleName, pprRuleName ) -import Maybes ( orElse ) import FastString import SrcLoc import DynFlags @@ -1536,6 +1535,7 @@ rnTyClDecl (DataDecl { tcdLName = tycon, tcdTyVars = tyvars, ; typeintype <- xoptM LangExt.TypeInType ; let cusk = hsTvbAllKinded tyvars' && (not typeintype || no_rhs_kvs) + ; traceRn "rndata" (ppr tycon <+> ppr cusk <+> ppr no_rhs_kvs) ; return (DataDecl { tcdLName = tycon', tcdTyVars = tyvars' , tcdFixity = fixity , tcdDataDefn = defn', tcdDataCusk = cusk @@ -1872,52 +1872,90 @@ rnConDecls :: [LConDecl GhcPs] -> RnM ([LConDecl GhcRn], FreeVars) rnConDecls = mapFvRn (wrapLocFstM rnConDecl) rnConDecl :: ConDecl GhcPs -> RnM (ConDecl GhcRn, FreeVars) -rnConDecl decl@(ConDeclH98 { con_name = name, con_qvars = qtvs - , con_cxt = mcxt, con_details = details +rnConDecl decl@(ConDeclH98 { con_name = name, con_ex_tvs = ex_tvs + , con_mb_cxt = mcxt, con_args = args , con_doc = mb_doc }) - = do { _ <- addLocM checkConName name - ; new_name <- lookupLocatedTopBndrRn name - ; mb_doc' <- rnMbLHsDoc mb_doc - - ; let doc = ConDeclCtx [new_name] - qtvs' = qtvs `orElse` mkHsQTvs [] - body_kvs = [] -- Consider data T a = forall (b::k). MkT (...) - -- The 'k' will already be in scope from the - -- bindHsQTyVars for the entire DataDecl - -- So there can be no new body_kvs here - ; bindHsQTyVars doc (Just $ inHsDocContext doc) Nothing body_kvs qtvs' $ - \new_tyvars _ -> do - { (new_context, fvs1) <- case mcxt of - Nothing -> return (Nothing,emptyFVs) - Just lcxt -> do { (lctx',fvs) <- rnContext doc lcxt - ; return (Just lctx',fvs) } - ; (new_details, fvs2) <- rnConDeclDetails (unLoc new_name) doc details - ; let (new_details',fvs3) = (new_details,emptyFVs) + = do { _ <- addLocM checkConName name + ; new_name <- lookupLocatedTopBndrRn name + ; mb_doc' <- rnMbLHsDoc mb_doc + + -- We bind no implicit binders here; this is just like + -- a nested HsForAllTy. E.g. consider + -- data T a = forall (b::k). MkT (...) + -- The 'k' will already be in scope from the bindHsQTyVars + -- for the data decl itself. So we'll get + -- data T {k} a = ... + -- And indeed we may later discover (a::k). But that's the + -- scoping we get. So no implicit binders at the existential forall + + ; let ctxt = ConDeclCtx [new_name] + ; bindLHsTyVarBndrs ctxt (Just (inHsDocContext ctxt)) + Nothing ex_tvs $ \ new_ex_tvs -> + do { (new_context, fvs1) <- rnMbContext ctxt mcxt + ; (new_args, fvs2) <- rnConDeclDetails (unLoc new_name) ctxt args + ; let all_fvs = fvs1 `plusFV` fvs2 ; traceRn "rnConDecl" (ppr name <+> vcat - [ text "qtvs:" <+> ppr qtvs - , text "qtvs':" <+> ppr qtvs' ]) - ; let all_fvs = fvs1 `plusFV` fvs2 `plusFV` fvs3 - new_tyvars' = case qtvs of - Nothing -> Nothing - Just _ -> Just new_tyvars - ; return (decl { con_name = new_name, con_qvars = new_tyvars' - , con_cxt = new_context, con_details = new_details' + [ text "ex_tvs:" <+> ppr ex_tvs + , text "new_ex_dqtvs':" <+> ppr new_ex_tvs ]) + + ; return (decl { con_name = new_name, con_ex_tvs = new_ex_tvs + , con_mb_cxt = new_context, con_args = new_args , con_doc = mb_doc' }, all_fvs) }} -rnConDecl decl@(ConDeclGADT { con_names = names, con_type = ty +rnConDecl decl@(ConDeclGADT { con_names = names + , con_forall = explicit_forall + , con_qvars = qtvs + , con_mb_cxt = mcxt + , con_args = args + , con_res_ty = res_ty , con_doc = mb_doc }) = do { mapM_ (addLocM checkConName) names - ; new_names <- mapM lookupLocatedTopBndrRn names - ; let doc = ConDeclCtx new_names - ; mb_doc' <- rnMbLHsDoc mb_doc - - ; (ty', fvs) <- rnHsSigType doc ty - ; traceRn "rnConDecl" (ppr names <+> vcat - [ text "fvs:" <+> ppr fvs ]) - ; return (decl { con_names = new_names, con_type = ty' + ; new_names <- mapM lookupLocatedTopBndrRn names + ; mb_doc' <- rnMbLHsDoc mb_doc + + ; let explicit_tkvs = hsQTvExplicit qtvs + theta = hsConDeclTheta mcxt + arg_tys = hsConDeclArgTys args + ; free_tkvs <- extractHsTysRdrTyVarsDups (res_ty : theta ++ arg_tys) + ; free_tkvs <- extractHsTvBndrs explicit_tkvs free_tkvs + + ; let ctxt = ConDeclCtx new_names + mb_ctxt = Just (inHsDocContext ctxt) + + ; traceRn "rnConDecl" (ppr names $$ ppr free_tkvs $$ ppr explicit_forall ) + ; rnImplicitBndrs (not explicit_forall) ctxt free_tkvs $ \ implicit_tkvs -> + bindLHsTyVarBndrs ctxt mb_ctxt Nothing explicit_tkvs $ \ explicit_tkvs -> + do { (new_cxt, fvs1) <- rnMbContext ctxt mcxt + ; (new_args, fvs2) <- rnConDeclDetails (unLoc (head new_names)) ctxt args + ; (new_res_ty, fvs3) <- rnLHsType ctxt res_ty + + ; let all_fvs = fvs1 `plusFV` fvs2 `plusFV` fvs3 + (args', res_ty') + = case args of + InfixCon {} -> pprPanic "rnConDecl" (ppr names) + RecCon {} -> (new_args, new_res_ty) + PrefixCon as | (arg_tys, final_res_ty) <- splitHsFunType new_res_ty + -> ASSERT( null as ) + -- See Note [GADT abstract syntax] in HsDecls + (PrefixCon arg_tys, final_res_ty) + + new_qtvs = HsQTvs { hsq_implicit = implicit_tkvs + , hsq_explicit = explicit_tkvs + , hsq_dependent = emptyNameSet } + + ; traceRn "rnConDecl2" (ppr names $$ ppr implicit_tkvs $$ ppr explicit_tkvs) + ; return (decl { con_names = new_names + , con_qvars = new_qtvs, con_mb_cxt = new_cxt + , con_args = args', con_res_ty = res_ty' , con_doc = mb_doc' }, - fvs) } + all_fvs) } } + +rnMbContext :: HsDocContext -> Maybe (LHsContext GhcPs) + -> RnM (Maybe (LHsContext GhcRn), FreeVars) +rnMbContext _ Nothing = return (Nothing, emptyFVs) +rnMbContext doc (Just cxt) = do { (ctx',fvs) <- rnContext doc cxt + ; return (Just ctx',fvs) } rnConDeclDetails :: Name |