Commit 9612e91c authored by Richard Eisenberg's avatar Richard Eisenberg Committed by Marge Bot

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
f93c9517.

Fixes #16980

Test cases: th/T16980{,a}
parent bf02c264
Pipeline #11112 failed with stages
in 212 minutes and 44 seconds
......@@ -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)
......
......@@ -1394,7 +1394,7 @@ repE (ArithSeq _ _ aseq) =
repE (HsSpliceE _ splice) = repSplice splice
repE (HsStatic _ e) = repLE e >>= rep2 staticEName . (:[]) . unC
repE (HsUnboundVar _ uv) = do
occ <- occNameLit (unboundVarOcc uv)
occ <- occNameLit uv
sname <- repNameS occ
repUnboundVar sname
......
......@@ -2102,7 +2102,7 @@ patSynErr l e explanation =
; return (cL l hsHoleExpr) }
hsHoleExpr :: HsExpr (GhcPass id)
hsHoleExpr = HsUnboundVar noExtField (TrueExprHole (mkVarOcc "_"))
hsHoleExpr = HsUnboundVar noExtField (mkVarOcc "_")
-- | See Note [Ambiguous syntactic categories] and Note [PatBuilder]
data PatBuilder p
......
......@@ -108,11 +108,7 @@ rnUnboundVar v
then -- Treat this as a "hole"
-- Do not fail right now; instead, return HsUnboundVar
-- and let the type checker report the error
do { let occ = rdrNameOcc v
; uv <- if startsWithUnderscore occ
then return (TrueExprHole occ)
else OutOfScope occ <$> getGlobalRdrEnv
; return (HsUnboundVar noExtField uv, emptyFVs) }
return (HsUnboundVar noExtField (rdrNameOcc v), emptyFVs)
else -- Fail immediately (qualified name)
do { n <- reportUnboundName v
......
......@@ -1141,7 +1141,7 @@ badRuleLhsErr name lhs bad_e
text "LHS must be of form (f e1 .. en) where f is not forall'd"
where
err = case bad_e of
HsUnboundVar _ uv -> notInScopeErr (mkRdrUnqual (unboundVarOcc uv))
HsUnboundVar _ uv -> notInScopeErr (mkRdrUnqual uv)
_ -> text "Illegal expression:" <+> ppr bad_e
{- **************************************************************
......
......@@ -1180,7 +1180,7 @@ mkOpAppRn e1 op fix e2 -- Default case, no rearrangment
-- | Name of an operator in an operator application or section
data OpName = NormalOp Name -- ^ A normal identifier
| NegateOp -- ^ Prefix negation
| UnboundOp UnboundVar -- ^ An unbound indentifier
| UnboundOp OccName -- ^ An unbound indentifier
| RecFldOp (AmbiguousFieldOcc GhcRn)
-- ^ A (possibly ambiguous) record field occurrence
......@@ -1347,7 +1347,7 @@ checkSectionPrec direction section op arg
lookupFixityOp :: OpName -> RnM Fixity
lookupFixityOp (NormalOp n) = lookupFixityRn n
lookupFixityOp NegateOp = lookupFixityRn negateName
lookupFixityOp (UnboundOp u) = lookupFixityRn (mkUnboundName (unboundVarOcc u))
lookupFixityOp (UnboundOp u) = lookupFixityRn (mkUnboundName u)
lookupFixityOp (RecFldOp f) = lookupFieldFixityRn f
......
......@@ -521,7 +521,6 @@ mergeSignatures
-- tcg_dus?
-- tcg_th_used = tcg_th_used orig_tcg_env,
-- tcg_th_splice_used = tcg_th_splice_used orig_tcg_env
-- tcg_th_top_level_locs = tcg_th_top_level_locs orig_tcg_env
}) $ do
tcg_env <- getGblEnv
......
......@@ -32,6 +32,7 @@ import FamInst ( tcTopNormaliseNewTypeTF_maybe )
import Var
import VarEnv( mkInScopeSet )
import VarSet( delVarSetList )
import OccName ( OccName )
import Outputable
import DynFlags( DynFlags )
import NameSet
......@@ -134,8 +135,8 @@ canonicalize (CFunEqCan { cc_ev = ev
= {-# SCC "canEqLeafFunEq" #-}
canCFunEqCan ev fn xis1 fsk
canonicalize (CHoleCan { cc_ev = ev, cc_hole = hole })
= canHole ev hole
canonicalize (CHoleCan { cc_ev = ev, cc_occ = occ, cc_hole = hole })
= canHole ev occ hole
{-
************************************************************************
......@@ -640,13 +641,14 @@ canIrred ev
_ -> continueWith $
mkIrredCt new_ev } }
canHole :: CtEvidence -> Hole -> TcS (StopOrContinue Ct)
canHole ev hole
canHole :: CtEvidence -> OccName -> HoleSort -> TcS (StopOrContinue Ct)
canHole ev occ hole_sort
= do { let pred = ctEvPred ev
; (xi,co) <- flatten FM_SubstOnly ev pred -- co :: xi ~ pred
; rewriteEvidence ev xi co `andWhenContinue` \ new_ev ->
do { updInertIrreds (`snocCts` (CHoleCan { cc_ev = new_ev
, cc_hole = hole }))
, cc_occ = occ
, cc_hole = hole_sort }))
; stopWith new_ev "Emit insoluble hole" } }
......
......@@ -33,11 +33,9 @@ import Class
import DataCon
import TcEvidence
import TcEvTerm
import GHC.Hs.Expr ( UnboundVar(..) )
import GHC.Hs.Binds ( PatSynBind(..) )
import Name
import RdrName ( lookupGlobalRdrEnv, lookupGRE_Name, GlobalRdrEnv
, mkRdrUnqual, isLocalGRE, greSrcSpan )
import RdrName ( lookupGRE_Name, GlobalRdrEnv, mkRdrUnqual )
import PrelNames ( typeableClassName )
import Id
import Var
......@@ -62,7 +60,6 @@ import FV ( fvVarList, unionFV )
import Control.Monad ( when )
import Data.Foldable ( toList )
import Data.List ( partition, mapAccumL, nub, sortBy, unfoldr )
import qualified Data.Set as Set
import {-# SOURCE #-} TcHoleErrors ( findValidHoleFits )
......@@ -1098,105 +1095,63 @@ mkIrredErr ctxt cts
----------------
mkHoleError :: [Ct] -> ReportErrCtxt -> Ct -> TcM ErrMsg
mkHoleError _ _ ct@(CHoleCan { cc_hole = ExprHole (OutOfScope occ rdr_env0) })
-- Out-of-scope variables, like 'a', where 'a' isn't bound; suggest possible
-- in-scope variables in the message, and note inaccessible exact matches
= do { dflags <- getDynFlags
mkHoleError tidy_simples ctxt ct@(CHoleCan { cc_occ = occ, cc_hole = hole_sort })
| isOutOfScopeCt ct -- Out of scope variables, like 'a', where 'a' isn't bound
-- Suggest possible in-scope variables in the message
= do { dflags <- getDynFlags
; rdr_env <- getGlobalRdrEnv
; imp_info <- getImports
; curr_mod <- getModule
; hpt <- getHpt
; let suggs_msg = unknownNameSuggestions dflags hpt curr_mod rdr_env0
(tcl_rdr lcl_env) imp_info rdr
; rdr_env <- getGlobalRdrEnv
; splice_locs <- getTopLevelSpliceLocs
; let match_msgs = mk_match_msgs rdr_env splice_locs
; mkErrDocAt (RealSrcSpan err_loc) $
errDoc [out_of_scope_msg] [] (match_msgs ++ [suggs_msg]) }
where
rdr = mkRdrUnqual occ
ct_loc = ctLoc ct
lcl_env = ctLocEnv ct_loc
err_loc = tcl_loc lcl_env
hole_ty = ctEvPred (ctEvidence ct)
boring_type = isTyVarTy hole_ty
out_of_scope_msg -- Print v :: ty only if the type has structure
| boring_type = hang herald 2 (ppr occ)
| otherwise = hang herald 2 (pp_with_type occ hole_ty)
; mkErrDocAt (RealSrcSpan (tcl_loc lcl_env)) $
errDoc [out_of_scope_msg] []
[unknownNameSuggestions dflags hpt curr_mod rdr_env
(tcl_rdr lcl_env) imp_info (mkRdrUnqual occ)] }
herald | isDataOcc occ = text "Data constructor not in scope:"
| otherwise = text "Variable not in scope:"
-- Indicate if the out-of-scope variable exactly (and unambiguously) matches
-- a top-level binding in a later inter-splice group; see Note [OutOfScope
-- exact matches]
mk_match_msgs rdr_env splice_locs
= let gres = filter isLocalGRE (lookupGlobalRdrEnv rdr_env occ)
in case gres of
[gre]
| RealSrcSpan bind_loc <- greSrcSpan gre
-- Find splice between the unbound variable and the match; use
-- lookupLE, not lookupLT, since match could be in the splice
, Just th_loc <- Set.lookupLE bind_loc splice_locs
, err_loc < th_loc
-> [mk_bind_scope_msg bind_loc th_loc]
_ -> []
mk_bind_scope_msg bind_loc th_loc
| is_th_bind
= hang (quotes (ppr occ) <+> parens (text "splice on" <+> th_rng))
2 (text "is not in scope before line" <+> int th_start_ln)
| otherwise
= hang (quotes (ppr occ) <+> bind_rng <+> text "is not in scope")
2 (text "before the splice on" <+> th_rng)
where
bind_rng = parens (text "line" <+> int bind_ln)
th_rng
| th_start_ln == th_end_ln = single
| otherwise = multi
single = text "line" <+> int th_start_ln
multi = text "lines" <+> int th_start_ln <> text "-" <> int th_end_ln
bind_ln = srcSpanStartLine bind_loc
th_start_ln = srcSpanStartLine th_loc
th_end_ln = srcSpanEndLine th_loc
is_th_bind = th_loc `containsSpan` bind_loc
mkHoleError tidy_simples ctxt ct@(CHoleCan { cc_hole = hole })
-- Explicit holes, like "_" or "_f"
| otherwise -- Explicit holes, like "_" or "_f"
= do { (ctxt, binds_msg, ct) <- relevantBindings False ctxt ct
-- The 'False' means "don't filter the bindings"; see #8191
-- The 'False' means "don't filter the bindings"; see Trac #8191
; show_hole_constraints <- goptM Opt_ShowHoleConstraints
; let constraints_msg
| isExprHoleCt ct, show_hole_constraints
= givenConstraintsMsg ctxt
| otherwise = empty
= givenConstraintsMsg ctxt
| otherwise
= empty
; show_valid_hole_fits <- goptM Opt_ShowValidHoleFits
; (ctxt, sub_msg) <- if show_valid_hole_fits
then validHoleFits ctxt tidy_simples ct
else return (ctxt, empty)
; mkErrorMsgFromCt ctxt ct $
important hole_msg `mappend`
relevant_bindings (binds_msg $$ constraints_msg) `mappend`
valid_hole_fits sub_msg}
valid_hole_fits sub_msg }
where
occ = holeOcc hole
hole_ty = ctEvPred (ctEvidence ct)
hole_kind = tcTypeKind hole_ty
tyvars = tyCoVarsOfTypeList hole_ty
hole_msg = case hole of
ExprHole {} -> vcat [ hang (text "Found hole:")
2 (pp_with_type occ hole_ty)
, tyvars_msg, expr_hole_hint ]
TypeHole {} -> vcat [ hang (text "Found type wildcard" <+>
quotes (ppr occ))
2 (text "standing for" <+>
quotes pp_hole_type_with_kind)
, tyvars_msg, type_hole_hint ]
ct_loc = ctLoc ct
lcl_env = ctLocEnv ct_loc
hole_ty = ctEvPred (ctEvidence ct)
hole_kind = tcTypeKind hole_ty
tyvars = tyCoVarsOfTypeList hole_ty
boring_type = isTyVarTy hole_ty
out_of_scope_msg -- Print v :: ty only if the type has structure
| boring_type = hang herald 2 (ppr occ)
| otherwise = hang herald 2 pp_with_type
pp_with_type = hang (pprPrefixOcc occ) 2 (dcolon <+> pprType hole_ty)
herald | isDataOcc occ = text "Data constructor not in scope:"
| otherwise = text "Variable not in scope:"
hole_msg = case hole_sort of
ExprHole -> vcat [ hang (text "Found hole:")
2 pp_with_type
, tyvars_msg, expr_hole_hint ]
TypeHole -> vcat [ hang (text "Found type wildcard" <+> quotes (ppr occ))
2 (text "standing for" <+> quotes pp_hole_type_with_kind)
, tyvars_msg, type_hole_hint ]
pp_hole_type_with_kind
| isLiftedTypeKind hole_kind
......@@ -1272,9 +1227,6 @@ givenConstraintsMsg ctxt =
hang (text "Constraints include")
2 (vcat $ map pprConstraint constraints)
pp_with_type :: OccName -> Type -> SDoc
pp_with_type occ ty = hang (pprPrefixOcc occ) 2 (dcolon <+> pprType ty)
----------------
mkIPErr :: ReportErrCtxt -> [Ct] -> TcM ErrMsg
mkIPErr ctxt cts
......@@ -1295,7 +1247,6 @@ mkIPErr ctxt cts
(ct1:_) = cts
{-
Note [Constraints include ...]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'givenConstraintsMsg' returns the "Constraints include ..." message enabled by
......@@ -1313,112 +1264,6 @@ would generate the message:
Constraints are displayed in order from innermost (closest to the hole) to
outermost. There's currently no filtering or elimination of duplicates.
Note [OutOfScope exact matches]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When constructing an out-of-scope error message, we not only generate a list of
possible in-scope alternatives but also search for an exact, unambiguous match
in a later inter-splice group. If we find such a match, we report its presence
(and indirectly, its scope) in the message. For example, if a module A contains
the following declarations,
foo :: Int
foo = x
$(return []) -- Empty top-level splice
x :: Int
x = 23
we will issue an error similar to
A.hs:6:7: error:
• Variable not in scope: x :: Int
• ‘x’ (line 11) is not in scope before the splice on line 8
By providing information about the match, we hope to clarify why declaring a
variable after a top-level splice but using it before the splice generates an
out-of-scope error (a situation which is often confusing to Haskell newcomers).
Note that if we find multiple exact matches to the out-of-scope variable
(hereafter referred to as x), we report nothing. Such matches can only be
duplicate record fields, as the presence of any other duplicate top-level
declarations would have already halted compilation. But if these record fields
are declared in a later inter-splice group, then so too are their corresponding
types. Thus, these types must not occur in the inter-splice group containing x
(any unknown types would have already been reported), and so the matches to the
record fields are most likely coincidental.
One oddity of the exact match portion of the error message is that we specify
where the match to x is NOT in scope. Why not simply state where the match IS
in scope? It most cases, this would be just as easy and perhaps a little
clearer for the user. But now consider the following example:
{-# LANGUAGE TemplateHaskell #-}
module A where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
foo = x
$(do -------------------------------------------------
ds <- [d| ok1 = x
|]
addTopDecls ds
return [])
bar = $(do
ds <- [d| x = 23
ok2 = x
|]
addTopDecls ds
litE $ stringL "hello")
$(return []) -----------------------------------------
ok3 = x
Here, x is out-of-scope in the declaration of foo, and so we report
A.hs:8:7: error:
• Variable not in scope: x
• ‘x’ (line 16) is not in scope before the splice on lines 10-14
If we instead reported where x IS in scope, we would have to state that it is in
scope after the second top-level splice as well as among all the top-level
declarations added by both calls to addTopDecls. But doing so would not only
add complexity to the code but also overwhelm the user with unneeded
information.
The logic which determines where x is not in scope is straightforward: it simply
finds the last top-level splice which occurs after x but before (or at) the
match to x (assuming such a splice exists). In most cases, the check that the
splice occurs after x acts only as a sanity check. For example, when the match
to x is a non-TH top-level declaration and a splice S occurs before the match,
then x must precede S; otherwise, it would be in scope. But when dealing with
addTopDecls, this check serves a practical purpose. Consider the following
declarations:
$(do
ds <- [d| ok = x
x = 23
|]
addTopDecls ds
return [])
foo = x
In this case, x is not in scope in the declaration for foo. Since x occurs
AFTER the splice containing the match, the logic does not find any splices after
x but before or at its match, and so we report nothing about x's scope. If we
had not checked whether x occurs before the splice, we would have instead
reported that x is not in scope before the splice. While correct, such an error
message is more likely to confuse than to enlighten.
-}
{-
************************************************************************
* *
Equality errors
......
......@@ -1848,7 +1848,7 @@ tc_infer_id lbl id_name
| otherwise = return ()
tcUnboundId :: HsExpr GhcRn -> UnboundVar -> ExpRhoType -> TcM (HsExpr GhcTcId)
tcUnboundId :: HsExpr GhcRn -> OccName -> ExpRhoType -> TcM (HsExpr GhcTcId)
-- Typecheck an occurrence of an unbound Id
--
-- Some of these started life as a true expression hole "_".
......@@ -1857,12 +1857,11 @@ tcUnboundId :: HsExpr GhcRn -> UnboundVar -> ExpRhoType -> TcM (HsExpr GhcTcId)
-- We turn all of them into HsVar, since HsUnboundVar can't contain an
-- Id; and indeed the evidence for the CHoleCan does bind it, so it's
-- not unbound any more!
tcUnboundId rn_expr unbound res_ty
tcUnboundId rn_expr occ res_ty
= do { ty <- newOpenFlexiTyVarTy -- Allow Int# etc (#12531)
; let occ = unboundVarOcc unbound
; name <- newSysName occ
; let ev = mkLocalId name ty
; can <- newHoleCt (ExprHole unbound) ev ty
; can <- newHoleCt ExprHole ev ty
; emitInsoluble can
; tcWrapResultO (UnboundOccurrenceOf occ) rn_expr
(HsVar noExtField (noLoc ev)) ty res_ty }
......
......@@ -960,7 +960,8 @@ zonkExpr env (HsWrap x co_fn expr)
new_expr <- zonkExpr env1 expr
return (HsWrap x new_co_fn new_expr)
zonkExpr _ e@(HsUnboundVar {}) = return e
zonkExpr _ e@(HsUnboundVar {})
= return e
zonkExpr _ expr = pprPanic "zonkExpr" (ppr expr)
......
......@@ -183,13 +183,14 @@ newWanteds :: CtOrigin -> ThetaType -> TcM [CtEvidence]
newWanteds orig = mapM (newWanted orig Nothing)
-- | Create a new 'CHoleCan' 'Ct'.
newHoleCt :: Hole -> Id -> Type -> TcM Ct
newHoleCt :: HoleSort -> Id -> Type -> TcM Ct
newHoleCt hole ev ty = do
loc <- getCtLocM HoleOrigin Nothing
pure $ CHoleCan { cc_ev = CtWanted { ctev_pred = ty
, ctev_dest = EvVarDest ev
, ctev_nosh = WDeriv
, ctev_loc = loc }
, cc_occ = getOccName ev
, cc_hole = hole }