Commit 96adf0e9 authored by thoughtpolice's avatar thoughtpolice

Improve error when using forall with UnicodeSyntax

Fixes Trac #7901.

'∀' is neither upper nor lowercase, unlike the 'f' in 'forall', so when
explicit forall is not enabled, it creates a parse error before reaching
the '.', which is where we give a nice message for ascii 'forall'.
Therefore, we make '∀' into a token as long as UnicodeSyntax is enabled,
which is safe because its caselessness means it can never be mistaken
for a symbol, and check extensions in the parser when the 'forall' rule
is used.
Authored-by: default avatarPaul Cavallaro <ptc@fb.com>
Authored-by: ajp's avatarAnders Papitto <anderspapitto@gmail.com>
Signed-off-by: thoughtpolice's avatarAustin Seipp <aseipp@pobox.com>
parent 5d77d8d4
......@@ -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
......
......@@ -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>"
]
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment