summaryrefslogtreecommitdiff
path: root/compiler/GHC/Rename
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2020-05-05 16:46:43 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-05-13 20:04:46 -0400
commit102cfd6784d16a0d0cc8bdf42d4de4c7b8dd0190 (patch)
tree4cf0015b9dd76f8aeda5728ada2aeafae0668625 /compiler/GHC/Rename
parentd880d6b2e48268f5ed4d3eb751fe24cc833e9221 (diff)
downloadhaskell-102cfd6784d16a0d0cc8bdf42d4de4c7b8dd0190.tar.gz
Factor out HsPatSigType for pat sigs/RULE term sigs (#16762)
This implements chunks (2) and (3) of https://gitlab.haskell.org/ghc/ghc/issues/16762#note_270170. Namely, it introduces a dedicated `HsPatSigType` AST type, which represents the types that can appear in pattern signatures and term-level `RULE` binders. Previously, these were represented with `LHsSigWcType`. Although `LHsSigWcType` is isomorphic to `HsPatSigType`, the intended semantics of the two types are slightly different, as evidenced by the fact that they have different code paths in the renamer and typechecker. See also the new `Note [Pattern signature binders and scoping]` in `GHC.Hs.Types`.
Diffstat (limited to 'compiler/GHC/Rename')
-rw-r--r--compiler/GHC/Rename/Bind.hs2
-rw-r--r--compiler/GHC/Rename/Expr.hs2
-rw-r--r--compiler/GHC/Rename/HsType.hs107
-rw-r--r--compiler/GHC/Rename/Module.hs4
-rw-r--r--compiler/GHC/Rename/Pat.hs8
5 files changed, 76 insertions, 47 deletions
diff --git a/compiler/GHC/Rename/Bind.hs b/compiler/GHC/Rename/Bind.hs
index fe7fb78b08..a2566220b6 100644
--- a/compiler/GHC/Rename/Bind.hs
+++ b/compiler/GHC/Rename/Bind.hs
@@ -955,7 +955,7 @@ renameSig _ (IdSig _ x)
renameSig ctxt sig@(TypeSig _ vs ty)
= do { new_vs <- mapM (lookupSigOccRn ctxt sig) vs
; let doc = TypeSigCtx (ppr_sig_bndrs vs)
- ; (new_ty, fvs) <- rnHsSigWcType BindUnlessForall doc ty
+ ; (new_ty, fvs) <- rnHsSigWcType doc ty
; return (TypeSig noExtField new_vs new_ty, fvs) }
renameSig ctxt sig@(ClassOpSig _ is_deflt vs ty)
diff --git a/compiler/GHC/Rename/Expr.hs b/compiler/GHC/Rename/Expr.hs
index 6ec473134d..65d119ab12 100644
--- a/compiler/GHC/Rename/Expr.hs
+++ b/compiler/GHC/Rename/Expr.hs
@@ -316,7 +316,7 @@ rnExpr (RecordUpd { rupd_expr = expr, rupd_flds = rbinds })
, fvExpr `plusFV` fvRbinds) }
rnExpr (ExprWithTySig _ expr pty)
- = do { (pty', fvTy) <- rnHsSigWcType BindUnlessForall ExprWithTySigCtx pty
+ = do { (pty', fvTy) <- rnHsSigWcType ExprWithTySigCtx pty
; (expr', fvExpr) <- bindSigTyVarsFV (hsWcScopedTvs pty') $
rnLExpr expr
; return (ExprWithTySig noExtField expr' pty', fvExpr `plusFV` fvTy) }
diff --git a/compiler/GHC/Rename/HsType.hs b/compiler/GHC/Rename/HsType.hs
index 537b2a47f0..f3727221a0 100644
--- a/compiler/GHC/Rename/HsType.hs
+++ b/compiler/GHC/Rename/HsType.hs
@@ -13,7 +13,7 @@ module GHC.Rename.HsType (
rnHsType, rnLHsType, rnLHsTypes, rnContext,
rnHsKind, rnLHsKind, rnLHsTypeArgs,
rnHsSigType, rnHsWcType,
- HsSigWcTypeScoping(..), rnHsSigWcType, rnHsSigWcTypeScoped,
+ HsSigWcTypeScoping(..), rnHsSigWcType, rnHsPatSigType,
newTyVarNameRn,
rnConDeclFields,
rnLTyVar,
@@ -71,11 +71,11 @@ import Control.Monad ( unless, when )
{-
These type renamers are in a separate module, rather than in (say) GHC.Rename.Module,
-to break several loop.
+to break several loops.
*********************************************************
* *
- HsSigWcType (i.e with wildcards)
+ HsSigWcType and HsPatSigType (i.e with wildcards)
* *
*********************************************************
-}
@@ -85,46 +85,77 @@ data HsSigWcTypeScoping
-- ^ Always bind any free tyvars of the given type, regardless of whether we
-- have a forall at the top.
--
- -- For pattern type sigs and rules we /do/ want to bring those type
+ -- For pattern type sigs, we /do/ want to bring those type
-- variables into scope, even if there's a forall at the top which usually
-- stops that happening, e.g:
--
- -- > \ (x :: forall a. a-> b) -> e
+ -- > \ (x :: forall a. a -> b) -> e
--
-- Here we do bring 'b' into scope.
+ --
+ -- RULES can also use 'AlwaysBind', such as in the following example:
+ --
+ -- > {-# RULES \"f\" forall (x :: forall a. a -> b). f x = ... b ... #-}
+ --
+ -- This only applies to RULES that do not explicitly bind their type
+ -- variables. If a RULE explicitly quantifies its type variables, then
+ -- 'NeverBind' is used instead. See also
+ -- @Note [Pattern signature binders and scoping]@ in "GHC.Hs.Types".
| BindUnlessForall
- -- ^ Unless there's forall at the top, do the same thing as 'AlwaysBind'
+ -- ^ Unless there's forall at the top, do the same thing as 'AlwaysBind'.
+ -- This is only ever used in places where the \"@forall@-or-nothing\" rule
+ -- is in effect. See @Note [forall-or-nothing rule]@.
| NeverBind
- -- ^ Never bind any free tyvars
-
-rnHsSigWcType :: HsSigWcTypeScoping -> HsDocContext -> LHsSigWcType GhcPs
+ -- ^ Never bind any free tyvars. This is used for RULES that have both
+ -- explicit type and term variable binders, e.g.:
+ --
+ -- > {-# RULES \"const\" forall a. forall (x :: a) y. const x y = x #-}
+ --
+ -- The presence of the type variable binder @forall a.@ implies that the
+ -- free variables in the types of the term variable binders @x@ and @y@
+ -- are /not/ bound. In the example above, there are no such free variables,
+ -- but if the user had written @(y :: b)@ instead of @y@ in the term
+ -- variable binders, then @b@ would be rejected for being out of scope.
+ -- See also @Note [Pattern signature binders and scoping]@ in
+ -- "GHC.Hs.Types".
+
+rnHsSigWcType :: HsDocContext -> LHsSigWcType GhcPs
-> RnM (LHsSigWcType GhcRn, FreeVars)
-rnHsSigWcType scoping doc sig_ty
- = rn_hs_sig_wc_type scoping doc sig_ty $ \sig_ty' ->
- return (sig_ty', emptyFVs)
-
-rnHsSigWcTypeScoped :: HsSigWcTypeScoping
- -> HsDocContext -> LHsSigWcType GhcPs
- -> (LHsSigWcType GhcRn -> RnM (a, FreeVars))
- -> RnM (a, FreeVars)
+rnHsSigWcType doc (HsWC { hswc_body = HsIB { hsib_body = hs_ty }})
+ = rn_hs_sig_wc_type BindUnlessForall doc hs_ty $ \nwcs imp_tvs body ->
+ let ib_ty = HsIB { hsib_ext = imp_tvs, hsib_body = body }
+ wc_ty = HsWC { hswc_ext = nwcs, hswc_body = ib_ty } in
+ pure (wc_ty, emptyFVs)
+
+rnHsPatSigType :: HsSigWcTypeScoping
+ -> HsDocContext -> HsPatSigType GhcPs
+ -> (HsPatSigType GhcRn -> RnM (a, FreeVars))
+ -> RnM (a, FreeVars)
-- Used for
--- - Signatures on binders in a RULE
--- - Pattern type signatures
+-- - Pattern type signatures, which are only allowed with ScopedTypeVariables
+-- - Signatures on binders in a RULE, which are allowed even if
+-- ScopedTypeVariables isn't enabled
-- Wildcards are allowed
--- type signatures on binders only allowed with ScopedTypeVariables
-rnHsSigWcTypeScoped scoping ctx sig_ty thing_inside
+--
+-- See Note [Pattern signature binders and scoping] in GHC.Hs.Types
+rnHsPatSigType scoping ctx sig_ty thing_inside
= do { ty_sig_okay <- xoptM LangExt.ScopedTypeVariables
- ; checkErr ty_sig_okay (unexpectedTypeSigErr sig_ty)
- ; rn_hs_sig_wc_type scoping ctx sig_ty thing_inside
- }
-
-rn_hs_sig_wc_type :: HsSigWcTypeScoping -> HsDocContext -> LHsSigWcType GhcPs
- -> (LHsSigWcType GhcRn -> RnM (a, FreeVars))
+ ; checkErr ty_sig_okay (unexpectedPatSigTypeErr sig_ty)
+ ; rn_hs_sig_wc_type scoping ctx (hsPatSigType sig_ty) $
+ \nwcs imp_tvs body ->
+ do { let sig_names = HsPSRn { hsps_nwcs = nwcs, hsps_imp_tvs = imp_tvs }
+ sig_ty' = HsPS { hsps_ext = sig_names, hsps_body = body }
+ ; thing_inside sig_ty'
+ } }
+
+-- The workhorse for rnHsSigWcType and rnHsPatSigType.
+rn_hs_sig_wc_type :: HsSigWcTypeScoping -> HsDocContext -> LHsType GhcPs
+ -> ([Name] -- Wildcard names
+ -> [Name] -- Implicitly bound type variable names
+ -> LHsType GhcRn
+ -> RnM (a, FreeVars))
-> RnM (a, FreeVars)
--- rn_hs_sig_wc_type is used for source-language type signatures
-rn_hs_sig_wc_type scoping ctxt
- (HsWC { hswc_body = HsIB { hsib_body = hs_ty }})
- thing_inside
+rn_hs_sig_wc_type scoping ctxt hs_ty thing_inside
= do { free_vars <- extractFilteredRdrTyVarsDups hs_ty
; (nwc_rdrs', tv_rdrs) <- partition_nwcs free_vars
; let nwc_rdrs = nubL nwc_rdrs'
@@ -134,10 +165,7 @@ rn_hs_sig_wc_type scoping ctxt
NeverBind -> []
; rnImplicitBndrs implicit_bndrs $ \ vars ->
do { (wcs, hs_ty', fvs1) <- rnWcBody ctxt nwc_rdrs hs_ty
- ; let sig_ty' = HsWC { hswc_ext = wcs, hswc_body = ib_ty' }
- ib_ty' = HsIB { hsib_ext = vars
- , hsib_body = hs_ty' }
- ; (res, fvs2) <- thing_inside sig_ty'
+ ; (res, fvs2) <- thing_inside wcs vars hs_ty'
; return (res, fvs1 `plusFV` fvs2) } }
rnHsWcType :: HsDocContext -> LHsWcType GhcPs -> RnM (LHsWcType GhcRn, FreeVars)
@@ -321,8 +349,9 @@ rnHsSigType ctx level (HsIB { hsib_body = hs_ty })
-- therefore an indication that the user is trying to be fastidious, so
-- we don't implicitly bind any variables.
--- | See note Note [forall-or-nothing rule]. This tiny little function is used
--- (rather than its small body inlined) to indicate we implementing that rule.
+-- | See Note [forall-or-nothing rule]. This tiny little function is used
+-- (rather than its small body inlined) to indicate that we are implementing
+-- that rule.
forAllOrNothing :: Bool
-- ^ True <=> explicit forall
-- E.g. f :: forall a. a->b
@@ -1396,8 +1425,8 @@ ppr_opfix (op, fixity) = pp_op <+> brackets (ppr fixity)
* *
***************************************************** -}
-unexpectedTypeSigErr :: LHsSigWcType GhcPs -> SDoc
-unexpectedTypeSigErr ty
+unexpectedPatSigTypeErr :: HsPatSigType GhcPs -> SDoc
+unexpectedPatSigTypeErr ty
= hang (text "Illegal type signature:" <+> quotes (ppr ty))
2 (text "Type signatures are only allowed in patterns with ScopedTypeVariables")
diff --git a/compiler/GHC/Rename/Module.hs b/compiler/GHC/Rename/Module.hs
index a4ca8a5165..2a09849e52 100644
--- a/compiler/GHC/Rename/Module.hs
+++ b/compiler/GHC/Rename/Module.hs
@@ -957,7 +957,7 @@ rnSrcDerivDecl (DerivDecl _ ty mds overlap)
; unless standalone_deriv_ok (addErr standaloneDerivErr)
; (mds', ty', fvs)
<- rnLDerivStrategy DerivDeclCtx mds $
- rnHsSigWcType BindUnlessForall DerivDeclCtx ty
+ rnHsSigWcType DerivDeclCtx ty
; warnNoDerivStrat mds' loc
; return (DerivDecl noExtField ty' mds' overlap, fvs) }
where
@@ -1028,7 +1028,7 @@ bindRuleTmVars doc tyvs vars names thing_inside
go ((L l (RuleBndrSig _ (L loc _) bsig)) : vars)
(n : ns) thing_inside
- = rnHsSigWcTypeScoped bind_free_tvs doc bsig $ \ bsig' ->
+ = rnHsPatSigType bind_free_tvs doc bsig $ \ bsig' ->
go vars ns $ \ vars' ->
thing_inside (L l (RuleBndrSig noExtField (L loc n) bsig') : vars')
diff --git a/compiler/GHC/Rename/Pat.hs b/compiler/GHC/Rename/Pat.hs
index 1e2bf09f45..09e2ea8cbe 100644
--- a/compiler/GHC/Rename/Pat.hs
+++ b/compiler/GHC/Rename/Pat.hs
@@ -218,9 +218,6 @@ matchNameMaker ctxt = LamMk report_unused
ThPatQuote -> False
_ -> True
-rnHsSigCps :: LHsSigWcType GhcPs -> CpsRn (LHsSigWcType GhcRn)
-rnHsSigCps sig = CpsRn (rnHsSigWcTypeScoped AlwaysBind PatCtx sig)
-
newPatLName :: NameMaker -> Located RdrName -> CpsRn (Located Name)
newPatLName name_maker rdr_name@(L loc _)
= do { name <- newPatName name_maker rdr_name
@@ -410,9 +407,12 @@ rnPatAndThen mk (SigPat x pat sig)
-- f ((Just (x :: a) :: Maybe a)
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~^ `a' is first bound here
-- ~~~~~~~~~~~~~~~^ the same `a' then used here
- = do { sig' <- rnHsSigCps sig
+ = do { sig' <- rnHsPatSigTypeAndThen sig
; pat' <- rnLPatAndThen mk pat
; return (SigPat x pat' sig' ) }
+ where
+ rnHsPatSigTypeAndThen :: HsPatSigType GhcPs -> CpsRn (HsPatSigType GhcRn)
+ rnHsPatSigTypeAndThen sig = CpsRn (rnHsPatSigType AlwaysBind PatCtx sig)
rnPatAndThen mk (LitPat x lit)
| HsString src s <- lit