summaryrefslogtreecommitdiff
path: root/compiler/GHC/Hs
diff options
context:
space:
mode:
authorRichard Eisenberg <rae@richarde.dev>2019-09-26 14:31:30 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-10-08 13:26:20 -0400
commit9612e91c793830b3049d2bc9a9ee28d9d82b928d (patch)
treef34d5c1f295026aaf1e706b8e2d20426fad6ac23 /compiler/GHC/Hs
parentbf02c26402cf926d41c006ab930ed9747e92a373 (diff)
downloadhaskell-9612e91c793830b3049d2bc9a9ee28d9d82b928d.tar.gz
Solve constraints from top-level groups sooner
Previously, all constraints from all top-level groups (as separated by top-level splices) were lumped together and solved at the end. This could leak metavariables to TH, though, and that's bad. This patch solves each group's constraints before running the next group's splice. Naturally, we now report fewer errors in some cases. One nice benefit is that this also fixes #11680, but in a much simpler way than the original fix for that ticket. Admittedly, the error messages degrade just a bit from the fix from #11680 (previously, we informed users about variables that will be brought into scope below a top-level splice, and now we just report an out-of-scope error), but the amount of complexity required throughout GHC to get that error was just not worth it. This patch thus reverts much of f93c9517a2c6e158e4a5c5bc7a3d3f88cb4ed119. Fixes #16980 Test cases: th/T16980{,a}
Diffstat (limited to 'compiler/GHC/Hs')
-rw-r--r--compiler/GHC/Hs/Expr.hs115
1 files changed, 8 insertions, 107 deletions
diff --git a/compiler/GHC/Hs/Expr.hs b/compiler/GHC/Hs/Expr.hs
index cd1a9f62bd..a3ad2bcada 100644
--- a/compiler/GHC/Hs/Expr.hs
+++ b/compiler/GHC/Hs/Expr.hs
@@ -35,7 +35,6 @@ import CoreSyn
import DynFlags ( gopt, GeneralFlag(Opt_PrintExplicitCoercions) )
import Name
import NameSet
-import RdrName ( GlobalRdrEnv )
import BasicTypes
import ConLike
import SrcLoc
@@ -186,104 +185,6 @@ is Less Cool because
typecheck do-notation with (>>=) :: m1 a -> (a -> m2 b) -> m2 b.)
-}
--- | An unbound variable; used for treating
--- out-of-scope variables as expression holes
---
--- Either "x", "y" Plain OutOfScope
--- or "_", "_x" A TrueExprHole
---
--- Both forms indicate an out-of-scope variable, but the latter
--- indicates that the user /expects/ it to be out of scope, and
--- just wants GHC to report its type
-data UnboundVar
- = OutOfScope OccName GlobalRdrEnv -- ^ An (unqualified) out-of-scope
- -- variable, together with the GlobalRdrEnv
- -- with respect to which it is unbound
-
- -- See Note [OutOfScope and GlobalRdrEnv]
-
- | TrueExprHole OccName -- ^ A "true" expression hole (_ or _x)
-
- deriving Data
-
-instance Outputable UnboundVar where
- ppr (OutOfScope occ _) = text "OutOfScope" <> parens (ppr occ)
- ppr (TrueExprHole occ) = text "ExprHole" <> parens (ppr occ)
-
-unboundVarOcc :: UnboundVar -> OccName
-unboundVarOcc (OutOfScope occ _) = occ
-unboundVarOcc (TrueExprHole occ) = occ
-
-{-
-Note [OutOfScope and GlobalRdrEnv]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-To understand why we bundle a GlobalRdrEnv with an out-of-scope variable,
-consider the following module:
-
- module A where
-
- foo :: ()
- foo = bar
-
- bat :: [Double]
- bat = [1.2, 3.4]
-
- $(return [])
-
- bar = ()
- bad = False
-
-When A is compiled, the renamer determines that `bar` is not in scope in the
-declaration of `foo` (since `bar` is declared in the following inter-splice
-group). Once it has finished typechecking the entire module, the typechecker
-then generates the associated error message, which specifies both the type of
-`bar` and a list of possible in-scope alternatives:
-
- A.hs:6:7: error:
- • Variable not in scope: bar :: ()
- • ‘bar’ (line 13) is not in scope before the splice on line 11
- Perhaps you meant ‘bat’ (line 9)
-
-When it calls RnEnv.unknownNameSuggestions to identify these alternatives, the
-typechecker must provide a GlobalRdrEnv. If it provided the current one, which
-contains top-level declarations for the entire module, the error message would
-incorrectly suggest the out-of-scope `bar` and `bad` as possible alternatives
-for `bar` (see #11680). Instead, the typechecker must use the same
-GlobalRdrEnv the renamer used when it determined that `bar` is out-of-scope.
-
-To obtain this GlobalRdrEnv, can the typechecker simply use the out-of-scope
-`bar`'s location to either reconstruct it (from the current GlobalRdrEnv) or to
-look it up in some global store? Unfortunately, no. The problem is that
-location information is not always sufficient for this task. This is most
-apparent when dealing with the TH function addTopDecls, which adds its
-declarations to the FOLLOWING inter-splice group. Consider these declarations:
-
- ex9 = cat -- cat is NOT in scope here
-
- $(do -------------------------------------------------------------
- ds <- [d| f = cab -- cat and cap are both in scope here
- cat = ()
- |]
- addTopDecls ds
- [d| g = cab -- only cap is in scope here
- cap = True
- |])
-
- ex10 = cat -- cat is NOT in scope here
-
- $(return []) -----------------------------------------------------
-
- ex11 = cat -- cat is in scope
-
-Here, both occurrences of `cab` are out-of-scope, and so the typechecker needs
-the GlobalRdrEnvs which were used when they were renamed. These GlobalRdrEnvs
-are different (`cat` is present only in the GlobalRdrEnv for f's `cab'), but the
-locations of the two `cab`s are the same (they are both created in the same
-splice). Thus, we must include some additional information with each `cab` to
-allow the typechecker to obtain the correct GlobalRdrEnv. Clearly, the simplest
-information to use is the GlobalRdrEnv itself.
--}
-
-- | A Haskell expression.
data HsExpr p
= HsVar (XVar p)
@@ -292,7 +193,7 @@ data HsExpr p
-- See Note [Located RdrNames]
| HsUnboundVar (XUnboundVar p)
- UnboundVar -- ^ Unbound variable; also used for "holes"
+ OccName -- ^ Unbound variable; also used for "holes"
-- (_ or _x).
-- Turned from HsVar to HsUnboundVar by the
-- renamer, when it finds an out-of-scope
@@ -945,7 +846,7 @@ ppr_lexpr e = ppr_expr (unLoc e)
ppr_expr :: forall p. (OutputableBndrId (GhcPass p))
=> HsExpr (GhcPass p) -> SDoc
ppr_expr (HsVar _ (L _ v)) = pprPrefixOcc v
-ppr_expr (HsUnboundVar _ uv)= pprPrefixOcc (unboundVarOcc uv)
+ppr_expr (HsUnboundVar _ uv)= pprPrefixOcc uv
ppr_expr (HsConLikeOut _ c) = pprPrefixOcc c
ppr_expr (HsIPVar _ v) = ppr v
ppr_expr (HsOverLabel _ _ l)= char '#' <> ppr l
@@ -1129,12 +1030,12 @@ ppr_expr (HsRecFld _ f) = ppr f
ppr_expr (XExpr x) = ppr x
ppr_infix_expr :: (OutputableBndrId (GhcPass p)) => HsExpr (GhcPass p) -> Maybe SDoc
-ppr_infix_expr (HsVar _ (L _ v)) = Just (pprInfixOcc v)
-ppr_infix_expr (HsConLikeOut _ c)= Just (pprInfixOcc (conLikeName c))
-ppr_infix_expr (HsRecFld _ f) = Just (pprInfixOcc f)
-ppr_infix_expr (HsUnboundVar _ h@TrueExprHole{}) = Just (pprInfixOcc (unboundVarOcc h))
-ppr_infix_expr (HsWrap _ _ e) = ppr_infix_expr e
-ppr_infix_expr _ = Nothing
+ppr_infix_expr (HsVar _ (L _ v)) = Just (pprInfixOcc v)
+ppr_infix_expr (HsConLikeOut _ c) = Just (pprInfixOcc (conLikeName c))
+ppr_infix_expr (HsRecFld _ f) = Just (pprInfixOcc f)
+ppr_infix_expr (HsUnboundVar _ occ) = Just (pprInfixOcc occ)
+ppr_infix_expr (HsWrap _ _ e) = ppr_infix_expr e
+ppr_infix_expr _ = Nothing
ppr_apps :: (OutputableBndrId (GhcPass p))
=> HsExpr (GhcPass p)