summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/parser/Lexer.x9
-rw-r--r--compiler/parser/Parser.y.pp17
2 files changed, 20 insertions, 6 deletions
diff --git a/compiler/parser/Lexer.x b/compiler/parser/Lexer.x
index 4a64069d73..95880946bb 100644
--- a/compiler/parser/Lexer.x
+++ b/compiler/parser/Lexer.x
@@ -57,6 +57,8 @@ module Lexer (
extension, bangPatEnabled, datatypeContextsEnabled,
traditionalRecordSyntaxEnabled,
typeLiteralsEnabled,
+ explicitForallEnabled,
+ inRulePrag,
explicitNamespacesEnabled, sccProfilingOn, hpcEnabled,
addWarning,
lexTokenStream
@@ -711,8 +713,7 @@ reservedSymsFM = listToUFM $
,("∷", ITdcolon, unicodeSyntaxEnabled)
,("⇒", ITdarrow, unicodeSyntaxEnabled)
- ,("∀", ITforall, \i -> unicodeSyntaxEnabled i &&
- explicitForallEnabled i)
+ ,("∀", ITforall, unicodeSyntaxEnabled)
,("→", ITrarrow, unicodeSyntaxEnabled)
,("←", ITlarrow, unicodeSyntaxEnabled)
@@ -1931,8 +1932,8 @@ datatypeContextsEnabled :: Int -> Bool
datatypeContextsEnabled flags = testBit flags datatypeContextsBit
qqEnabled :: Int -> Bool
qqEnabled flags = testBit flags qqBit
--- inRulePrag :: Int -> Bool
--- inRulePrag flags = testBit flags inRulePragBit
+inRulePrag :: Int -> Bool
+inRulePrag flags = testBit flags inRulePragBit
rawTokenStreamEnabled :: Int -> Bool
rawTokenStreamEnabled flags = testBit flags rawTokenStreamBit
alternativeLayoutRule :: Int -> Bool
diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp
index 384fb537bf..9d087068bf 100644
--- a/compiler/parser/Parser.y.pp
+++ b/compiler/parser/Parser.y.pp
@@ -1050,7 +1050,8 @@ strict_mark :: { Located HsBang }
-- A ctype is a for-all type
ctype :: { LHsType RdrName }
- : 'forall' tv_bndrs '.' ctype { LL $ mkExplicitHsForAllTy $2 (noLoc []) $4 }
+ : 'forall' tv_bndrs '.' ctype {% hintExplicitForall (getLoc $1) >>
+ return (LL $ mkExplicitHsForAllTy $2 (noLoc []) $4) }
| context '=>' ctype { LL $ mkImplicitHsForAllTy $1 $3 }
-- A type of form (context => type) is an *implicit* HsForAllTy
| ipvar '::' type { LL (HsIParamTy (unLoc $1) $3) }
@@ -1068,7 +1069,8 @@ ctype :: { LHsType RdrName }
-- to 'field' or to 'Int'. So we must use `ctype` to describe the type.
ctypedoc :: { LHsType RdrName }
- : 'forall' tv_bndrs '.' ctypedoc { LL $ mkExplicitHsForAllTy $2 (noLoc []) $4 }
+ : 'forall' tv_bndrs '.' ctypedoc {% hintExplicitForall (getLoc $1) >>
+ return (LL $ mkExplicitHsForAllTy $2 (noLoc []) $4) }
| context '=>' ctypedoc { LL $ mkImplicitHsForAllTy $1 $3 }
-- A type of form (context => type) is an *implicit* HsForAllTy
| ipvar '::' type { LL (HsIParamTy (unLoc $1) $3) }
@@ -2240,4 +2242,15 @@ hintMultiWayIf span = do
mwiEnabled <- liftM ((Opt_MultiWayIf `xopt`) . dflags) getPState
unless mwiEnabled $ parseErrorSDoc span $
text "Multi-way if-expressions need -XMultiWayIf turned on"
+
+-- Hint about explicit-forall, assuming UnicodeSyntax is on
+hintExplicitForall :: SrcSpan -> P ()
+hintExplicitForall span = do
+ forall <- extension explicitForallEnabled
+ rulePrag <- extension inRulePrag
+ unless (forall || rulePrag) $ parseErrorSDoc span $ vcat
+ [ text "Illegal symbol '∀' in type"
+ , text "Perhaps you intended -XRankNTypes or similar flag"
+ , text "to enable explicit-forall syntax: ∀ <tvs>. <type>"
+ ]
}