[Git][ghc/ghc][wip/aidylns/ttg-remove-hsunboundvar-via-hshole] TTG: Remove HsUnboundVar, replace with HsHole, HsUnboundVarRn/Tc
Adriaan Leijnse (@aidylns)
gitlab at gitlab.haskell.org
Fri Sep 13 14:49:00 UTC 2024
Adriaan Leijnse pushed to branch wip/aidylns/ttg-remove-hsunboundvar-via-hshole at Glasgow Haskell Compiler / GHC
Commits:
7ed954d9 by Adriaan Leijnse at 2024-09-13T16:48:38+02:00
TTG: Remove HsUnboundVar, replace with HsHole, HsUnboundVarRn/Tc
This commit removes HsUnboundVar from the Language AST, which was used to parse
Holes to. Instead it introduces a new HsHole AST constructor for this purpose.
The renaming and type checking phases keep their original HsUnboundVar
implementation using HsUnboundVarRn and HsUnboundVarTc constructors (HsHole is
turned into HsUnboundVarRn during renaming).
Also, the note explaining Holes is rewritten to reflect the current state of the
code.
- - - - -
25 changed files:
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- testsuite/tests/perf/compiler/hard_hole_fits.hs
- testsuite/tests/perf/compiler/hard_hole_fits.stderr
- testsuite/tests/plugins/T20803-plugin/FixErrorsPlugin.hs
- utils/check-exact/ExactPrint.hs
Changes:
=====================================
compiler/GHC/Hs/Expr.hs
=====================================
@@ -208,9 +208,10 @@ data EpAnnHsCase = EpAnnHsCase
instance NoAnn EpAnnHsCase where
noAnn = EpAnnHsCase noAnn noAnn noAnn
-data EpAnnUnboundVar = EpAnnUnboundVar
- { hsUnboundBackquotes :: (EpaLocation, EpaLocation)
- , hsUnboundHole :: EpaLocation
+-- | ExactPrint annotation for holes.
+data EpAnnHole = EpAnnHole
+ { hsHoleBackquotes :: (EpaLocation, EpaLocation)
+ , hsHoleHole :: EpaLocation
} deriving Data
-- Record selectors at parse time are HsVar; they convert to HsRecSel
@@ -229,14 +230,6 @@ type instance XOverLabel GhcTc = DataConCantHappen
type instance XVar (GhcPass _) = NoExtField
-type instance XUnboundVar GhcPs = Maybe EpAnnUnboundVar
-type instance XUnboundVar GhcRn = NoExtField
-type instance XUnboundVar GhcTc = HoleExprRef
- -- We really don't need the whole HoleExprRef; just the IORef EvTerm
- -- would be enough. But then deriving a Data instance becomes impossible.
- -- Much, much easier just to define HoleExprRef with a Data instance and
- -- store the whole structure.
-
type instance XIPVar GhcPs = NoExtField
type instance XIPVar GhcRn = NoExtField
type instance XIPVar GhcTc = DataConCantHappen
@@ -382,6 +375,11 @@ type instance XEmbTy GhcTc = DataConCantHappen
-- A free-standing HsEmbTy is an error.
-- Valid usages are immediately desugared into Type.
+type instance XHole GhcPs = Maybe EpAnnHole
+-- After renaming holes are handled using HsUnboundVarRn/HsUnboundVarTc:
+type instance XHole GhcRn = DataConCantHappen
+type instance XHole GhcTc = DataConCantHappen
+
type instance XForAll GhcPs = NoExtField
type instance XForAll GhcRn = NoExtField
type instance XForAll GhcTc = DataConCantHappen
@@ -514,6 +512,10 @@ data XXExprGhcRn
-- Does not presist post renaming phase
-- See Part 3. of Note [Expanding HsDo with XXExprGhcRn]
-- in `GHC.Tc.Gen.Do`
+ | HsUnboundVarRn RdrName -- ^ Unbound variable.
+ -- Turned from HsVar to HsUnboundVarRn by the
+ -- renamer, when it finds an out-of-scope
+ -- variable.
-- | Wrap a located expression with a `PopErrCtxt`
@@ -594,6 +596,19 @@ data XXExprGhcTc
Int -- module-local tick number for True
Int -- module-local tick number for False
(LHsExpr GhcTc) -- sub-expression
+ | HsUnboundVarTc HoleExprRef RdrName
+ -- ^ Unbound variable; also used for "holes"
+ -- (_ or _x).
+ -- In the case of expression holes, the HoleExprRef is where the
+ -- erroring expression will be written after solving.
+ -- See Note [Holes in expressions] in GHC.Tc.Types.Constraint.
+ --
+ -- We really don't need the whole HoleExprRef; just
+ -- the IORef EvTerm would be enough. But then
+ -- deriving a Data instance becomes impossible.
+ -- Much, much easier just to define HoleExprRef
+ -- with a Data instance and store the whole
+ -- structure.
-- | Build a 'XXExprGhcRn' out of an extension constructor,
-- and the two components of the expansion: original and
@@ -654,7 +669,10 @@ ppr_lexpr e = ppr_expr (unLoc e)
ppr_expr :: forall p. (OutputableBndrId p)
=> HsExpr (GhcPass p) -> SDoc
ppr_expr (HsVar _ (L _ v)) = pprPrefixOcc v
-ppr_expr (HsUnboundVar _ uv) = pprPrefixOcc uv
+ppr_expr (HsHole x) = case ghcPass @p of
+ GhcPs -> pprPrefixOcc (mkUnqual varName (fsLit "_"))
+ GhcRn -> dataConCantHappen x
+ GhcTc -> dataConCantHappen x
ppr_expr (HsRecSel _ f) = pprPrefixOcc f
ppr_expr (HsIPVar _ v) = ppr v
ppr_expr (HsOverLabel s l) = case ghcPass @p of
@@ -879,6 +897,7 @@ instance Outputable HsThingRn where
instance Outputable XXExprGhcRn where
ppr (ExpandedThingRn o e) = ifPprDebug (braces $ vcat [ppr o, ppr e]) (ppr o)
ppr (PopErrCtxt e) = ifPprDebug (braces (text "<PopErrCtxt>" <+> ppr e)) (ppr e)
+ ppr (HsUnboundVarRn uv) = pprPrefixOcc uv
instance Outputable XXExprGhcTc where
ppr (WrapExpr (HsWrap co_fn e))
@@ -907,11 +926,15 @@ instance Outputable XXExprGhcTc where
ppr tickIdFalse,
text ">(",
ppr exp, text ")"]
+ ppr (HsUnboundVarTc _ uv) = pprPrefixOcc uv
ppr_infix_expr :: forall p. (OutputableBndrId p) => HsExpr (GhcPass p) -> Maybe SDoc
ppr_infix_expr (HsVar _ (L _ v)) = Just (pprInfixOcc v)
ppr_infix_expr (HsRecSel _ f) = Just (pprInfixOcc f)
-ppr_infix_expr (HsUnboundVar _ occ) = Just (pprInfixOcc occ)
+ppr_infix_expr (HsHole x) = case ghcPass @p of
+ GhcPs -> Just (pprInfixOcc (mkUnqual varName (fsLit "_")))
+ GhcRn -> dataConCantHappen x
+ GhcTc -> dataConCantHappen x
ppr_infix_expr (XExpr x) = case ghcPass @p of
GhcRn -> ppr_infix_expr_rn x
GhcTc -> ppr_infix_expr_tc x
@@ -920,6 +943,7 @@ ppr_infix_expr _ = Nothing
ppr_infix_expr_rn :: XXExprGhcRn -> Maybe SDoc
ppr_infix_expr_rn (ExpandedThingRn thing _) = ppr_infix_hs_expansion thing
ppr_infix_expr_rn (PopErrCtxt (L _ a)) = ppr_infix_expr a
+ppr_infix_expr_rn (HsUnboundVarRn occ) = Just (pprInfixOcc occ)
ppr_infix_expr_tc :: XXExprGhcTc -> Maybe SDoc
ppr_infix_expr_tc (WrapExpr (HsWrap _ e)) = ppr_infix_expr e
@@ -927,6 +951,7 @@ ppr_infix_expr_tc (ExpandedThingTc thing _) = ppr_infix_hs_expansion thing
ppr_infix_expr_tc (ConLikeTc {}) = Nothing
ppr_infix_expr_tc (HsTick {}) = Nothing
ppr_infix_expr_tc (HsBinTick {}) = Nothing
+ppr_infix_expr_tc (HsUnboundVarTc _ occ) = Just (pprInfixOcc occ)
ppr_infix_hs_expansion :: HsThingRn -> Maybe SDoc
ppr_infix_hs_expansion (OrigExpr e) = ppr_infix_expr e
@@ -974,7 +999,6 @@ hsExprNeedsParens prec = go
where
go :: HsExpr (GhcPass p) -> Bool
go (HsVar{}) = False
- go (HsUnboundVar{}) = False
go (HsIPVar{}) = False
go (HsOverLabel{}) = False
go (HsLit _ l) = hsLitNeedsParens prec l
@@ -1017,6 +1041,7 @@ hsExprNeedsParens prec = go
go (HsProjection{}) = True
go (HsGetField{}) = False
go (HsEmbTy{}) = prec > topPrec
+ go (HsHole{}) = False
go (HsForAll{}) = prec >= funPrec
go (HsQual{}) = prec >= funPrec
go (HsFunArr{}) = prec >= funPrec
@@ -1030,10 +1055,12 @@ hsExprNeedsParens prec = go
go_x_tc (ConLikeTc {}) = False
go_x_tc (HsTick _ (L _ e)) = hsExprNeedsParens prec e
go_x_tc (HsBinTick _ _ (L _ e)) = hsExprNeedsParens prec e
+ go_x_tc (HsUnboundVarTc {}) = False
go_x_rn :: XXExprGhcRn -> Bool
go_x_rn (ExpandedThingRn thing _) = hsExpandedNeedsParens thing
go_x_rn (PopErrCtxt (L _ a)) = hsExprNeedsParens prec a
+ go_x_rn (HsUnboundVarRn _) = False
hsExpandedNeedsParens :: HsThingRn -> Bool
hsExpandedNeedsParens (OrigExpr e) = hsExprNeedsParens prec e
@@ -1070,8 +1097,8 @@ isAtomicHsExpr (HsLit {}) = True
isAtomicHsExpr (HsOverLit {}) = True
isAtomicHsExpr (HsIPVar {}) = True
isAtomicHsExpr (HsOverLabel {}) = True
-isAtomicHsExpr (HsUnboundVar {}) = True
isAtomicHsExpr (HsRecSel{}) = True
+isAtomicHsExpr (HsHole{}) = True
isAtomicHsExpr (XExpr x)
| GhcTc <- ghcPass @p = go_x_tc x
| GhcRn <- ghcPass @p = go_x_rn x
@@ -1082,10 +1109,12 @@ isAtomicHsExpr (XExpr x)
go_x_tc (ConLikeTc {}) = True
go_x_tc (HsTick {}) = False
go_x_tc (HsBinTick {}) = False
+ go_x_tc (HsUnboundVarTc {}) = True
go_x_rn :: XXExprGhcRn -> Bool
go_x_rn (ExpandedThingRn thing _) = isAtomicExpandedThingRn thing
go_x_rn (PopErrCtxt (L _ a)) = isAtomicHsExpr a
+ go_x_rn (HsUnboundVarRn {}) = True
isAtomicExpandedThingRn :: HsThingRn -> Bool
isAtomicExpandedThingRn (OrigExpr e) = isAtomicHsExpr e
=====================================
compiler/GHC/Hs/Syn/Type.hs
=====================================
@@ -102,7 +102,6 @@ lhsExprType (L _ e) = hsExprType e
-- | Compute the 'Type' of an @'HsExpr' 'GhcTc'@ in a pure fashion.
hsExprType :: HsExpr GhcTc -> Type
hsExprType (HsVar _ (L _ id)) = idType id
-hsExprType (HsUnboundVar (HER _ ty _) _) = ty
hsExprType (HsRecSel _ (FieldOcc id _)) = idType id
hsExprType (HsOverLabel v _) = dataConCantHappen v
hsExprType (HsIPVar v _) = dataConCantHappen v
@@ -146,6 +145,7 @@ hsExprType (HsProc _ _ lcmd_top) = lhsCmdTopType lcmd_top
hsExprType (HsStatic (_, ty) _s) = ty
hsExprType (HsPragE _ _ e) = lhsExprType e
hsExprType (HsEmbTy x _) = dataConCantHappen x
+hsExprType (HsHole x) = dataConCantHappen x
hsExprType (HsQual x _ _) = dataConCantHappen x
hsExprType (HsForAll x _ _) = dataConCantHappen x
hsExprType (HsFunArr x _ _ _) = dataConCantHappen x
@@ -154,6 +154,7 @@ hsExprType (XExpr (ExpandedThingTc _ e)) = hsExprType e
hsExprType (XExpr (ConLikeTc con _ _)) = conLikeType con
hsExprType (XExpr (HsTick _ e)) = lhsExprType e
hsExprType (XExpr (HsBinTick _ _ e)) = lhsExprType e
+hsExprType (XExpr (HsUnboundVarTc (HER _ ty _) _)) = ty
arithSeqInfoType :: ArithSeqInfo GhcTc -> Type
arithSeqInfoType asi = mkListTy $ case asi of
=====================================
compiler/GHC/HsToCore/Expr.hs
=====================================
@@ -292,8 +292,8 @@ dsExpr (HsRecSel _ (FieldOcc id _))
return $ take maxConstructors cons_wo_field
-dsExpr (HsUnboundVar (HER ref _ _) _) = dsEvTerm =<< readMutVar ref
- -- See Note [Holes] in GHC.Tc.Types.Constraint
+dsExpr (HsHole x) = dataConCantHappen x
+ -- Holes are handled by HsUnboundVarTc.
dsExpr (HsPar _ e) = dsLExpr e
dsExpr (ExprWithTySig _ e _) = dsLExpr e
@@ -336,6 +336,9 @@ dsExpr e@(XExpr ext_expr_tc)
do { assert (exprType e2 `eqType` boolTy)
mkBinaryTickBox ixT ixF e2
}
+ HsUnboundVarTc (HER ref _ _) _ -> dsEvTerm =<< readMutVar ref
+ -- See Note [Holes in expressions] in GHC.Tc.Types.Constraint.
+
-- Strip ticks due to #21701, need to be invariant about warnings we produce whether
-- this is enabled or not.
=====================================
compiler/GHC/HsToCore/Quote.hs
=====================================
@@ -1674,9 +1674,6 @@ repE (HsTypedSplice n _) = rep_splice n
repE (HsUntypedSplice (HsUntypedSpliceNested n) _) = rep_splice n
repE e@(HsUntypedSplice (HsUntypedSpliceTop _ _) _) = pprPanic "repE: top level splice" (ppr e)
repE (HsStatic _ e) = repLE e >>= rep2 staticEName . (:[]) . unC
-repE (HsUnboundVar _ uv) = do
- name <- repRdrName uv
- repUnboundVar name
repE (HsGetField _ e (L _ (DotFieldOcc _ (L _ (FieldLabelString f))))) = do
e1 <- repLE e
repGetField e1 f
@@ -1713,10 +1710,14 @@ repE e@(XExpr (ExpandedThingRn o x))
= notHandled (ThExpressionForm e)
repE (XExpr (PopErrCtxt (L _ e))) = repE e
+repE (XExpr (HsUnboundVarRn uv)) = do
+ name <- repRdrName uv
+ repUnboundVar name
repE e@(HsPragE _ (HsPragSCC {}) _) = notHandled (ThCostCentres e)
repE e@(HsTypedBracket{}) = notHandled (ThExpressionForm e)
repE e@(HsUntypedBracket{}) = notHandled (ThExpressionForm e)
repE e@(HsProc{}) = notHandled (ThExpressionForm e)
+repE e@(HsHole{}) = notHandled (ThExpressionForm e)
repFunArr :: HsArrowOf (LocatedA (HsExpr GhcRn)) GhcRn -> MetaM (Core (M TH.Exp))
repFunArr HsUnrestrictedArrow{} = repConName unrestrictedFunTyConName
=====================================
compiler/GHC/HsToCore/Ticks.hs
=====================================
@@ -475,7 +475,6 @@ addBinTickLHsExpr boxLabel e@(L pos e0)
addTickHsExpr :: HsExpr GhcTc -> TM (HsExpr GhcTc)
addTickHsExpr e@(HsVar _ (L _ id)) = do freeVar id; return e
-addTickHsExpr e@(HsUnboundVar {}) = return e
addTickHsExpr e@(HsRecSel _ (FieldOcc id _)) = do freeVar id; return e
addTickHsExpr e@(HsIPVar {}) = return e
@@ -483,6 +482,7 @@ addTickHsExpr e@(HsOverLit {}) = return e
addTickHsExpr e@(HsOverLabel{}) = return e
addTickHsExpr e@(HsLit {}) = return e
addTickHsExpr e@(HsEmbTy {}) = return e
+addTickHsExpr e@(HsHole {}) = return e
addTickHsExpr e@(HsQual {}) = return e
addTickHsExpr e@(HsForAll {}) = return e
addTickHsExpr e@(HsFunArr {}) = return e
@@ -603,6 +603,7 @@ addTickHsExpr (XExpr (HsTick t e)) =
liftM (XExpr . HsTick t) (addTickLHsExprNever e)
addTickHsExpr (XExpr (HsBinTick t0 t1 e)) =
liftM (XExpr . HsBinTick t0 t1) (addTickLHsExprNever e)
+addTickHsExpr e@(XExpr (HsUnboundVarTc {})) = return e
addTickHsExpr (HsDo srcloc cxt (L l stmts))
= do { (stmts', _) <- addTickLStmts' forQual stmts (return ())
=====================================
compiler/GHC/Iface/Ext/Ast.hs
=====================================
@@ -1176,7 +1176,6 @@ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where
[ toHie $ C Use (L mspan var)
-- Patch up var location since typechecker removes it
]
- HsUnboundVar _ _ -> [] -- there is an unbound name here, but that causes trouble
HsRecSel _ fld ->
[ toHie $ RFC RecFieldOcc Nothing (L mspan fld)
]
@@ -1325,6 +1324,7 @@ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where
]
HsGetField {} -> []
HsProjection {} -> []
+ HsHole _ -> [] -- there is a hole here, but that causes trouble
XExpr x
| HieTc <- hiePass @p
-> case x of
@@ -1341,6 +1341,7 @@ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where
HsBinTick _ _ expr
-> [ toHie expr
]
+ HsUnboundVarTc _ _ -> [] -- there is an unbound name here, but that causes trouble
| otherwise -> []
-- NOTE: no longer have the location
=====================================
compiler/GHC/Parser.y
=====================================
@@ -3896,7 +3896,7 @@ qopm :: { forall b. DisambInfixOp b => PV (LocatedN b) } -- used in section
| hole_op { mkHsInfixHolePV $1 }
hole_op :: { LocatedN (HsExpr GhcPs) } -- used in sections
-hole_op : '`' '_' '`' { sLLa $1 $> (hsHoleExpr (Just $ EpAnnUnboundVar (glAA $1, glAA $3) (glAA $2))) }
+hole_op : '`' '_' '`' { sLLa $1 $> (HsHole (Just $ EpAnnHole (glAA $1, glAA $3) (glAA $2))) }
qvarop :: { LocatedN RdrName }
: qvarsym { $1 }
=====================================
compiler/GHC/Parser/PostProcess.hs
=====================================
@@ -109,7 +109,6 @@ module GHC.Parser.PostProcess (
withArrowParsingMode, withArrowParsingMode',
setTelescopeBndrsNameSpace,
PatBuilder,
- hsHoleExpr,
-- Type/datacon ambiguity resolution
DisambTD(..),
@@ -1899,11 +1898,11 @@ instance DisambECP (HsExpr GhcPs) where
type Body (HsExpr GhcPs) = HsExpr
ecpFromCmd' (L l c) = do
addError $ mkPlainErrorMsgEnvelope (locA l) $ PsErrArrowCmdInExpr c
- return (L l (hsHoleExpr noAnn))
+ return (L l (HsHole noAnn))
ecpFromExp' = return
ecpFromPat' p@(L l _) = do
addError $ mkPlainErrorMsgEnvelope (locA l) $ PsErrOrPatInExpr p
- return (L l (hsHoleExpr noAnn))
+ return (L l (HsHole noAnn))
mkHsProjUpdatePV l fields arg isPun anns = do
!cs <- getCommentsFor l
return $ mkRdrProjUpdate (EpAnn (spanAsAnchor l) noAnn cs) fields arg isPun anns
@@ -1952,7 +1951,7 @@ instance DisambECP (HsExpr GhcPs) where
mkHsOverLitPV (L (EpAnn l an csIn) a) = do
!cs <- getCommentsFor (locA l)
return $ L (EpAnn l an (cs Semi.<> csIn)) (HsOverLit NoExtField a)
- mkHsWildCardPV l = return $ L (noAnnSrcSpan l) (hsHoleExpr noAnn)
+ mkHsWildCardPV l = return $ L (noAnnSrcSpan l) (HsHole noAnn)
mkHsTySigPV l@(EpAnn anc an csIn) a sig anns = do
!cs <- getCommentsFor (locA l)
return $ L (EpAnn anc an (csIn Semi.<> cs)) (ExprWithTySig anns a (hsTypeToHsSigWcType sig))
@@ -1973,11 +1972,11 @@ instance DisambECP (HsExpr GhcPs) where
!cs <- getCommentsFor l
return $ L (EpAnn (spanAsAnchor l) noAnn cs) (SectionR noExtField op e)
mkHsAsPatPV l v _ e = addError (mkPlainErrorMsgEnvelope l $ PsErrTypeAppWithoutSpace (unLoc v) e)
- >> return (L (noAnnSrcSpan l) (hsHoleExpr noAnn))
+ >> return (L (noAnnSrcSpan l) (HsHole noAnn))
mkHsLazyPatPV l e _ = addError (mkPlainErrorMsgEnvelope l $ PsErrLazyPatWithoutSpace e)
- >> return (L (noAnnSrcSpan l) (hsHoleExpr noAnn))
+ >> return (L (noAnnSrcSpan l) (HsHole noAnn))
mkHsBangPatPV l e _ = addError (mkPlainErrorMsgEnvelope l $ PsErrBangPatWithoutSpace e)
- >> return (L (noAnnSrcSpan l) (hsHoleExpr noAnn))
+ >> return (L (noAnnSrcSpan l) (HsHole noAnn))
mkSumOrTuplePV = mkSumOrTupleExpr
mkHsEmbTyPV l toktype ty =
return $ L (noAnnSrcSpan l) $
@@ -2004,9 +2003,6 @@ instance DisambECP (HsExpr GhcPs) where
(PsErrUnallowedPragma prag)
rejectPragmaPV _ = return ()
-hsHoleExpr :: Maybe EpAnnUnboundVar -> HsExpr GhcPs
-hsHoleExpr anns = HsUnboundVar anns (mkRdrUnqual (mkVarOccFS (fsLit "_")))
-
instance DisambECP (PatBuilder GhcPs) where
type Body (PatBuilder GhcPs) = PatBuilder
ecpFromCmd' (L l c) = addFatalError $ mkPlainErrorMsgEnvelope (locA l) $ PsErrArrowCmdInPat c
=====================================
compiler/GHC/Rename/Expr.hs
=====================================
@@ -320,7 +320,7 @@ rnUnboundVar v = do
deferOutofScopeVariables <- goptM Opt_DeferOutOfScopeVariables
-- See Note [Reporting unbound names] for difference between qualified and unqualified names.
unless (isUnqual v || deferOutofScopeVariables) (reportUnboundName v >> return ())
- return (HsUnboundVar noExtField v, emptyFVs)
+ return (XExpr (HsUnboundVarRn v), emptyFVs)
rnExpr (HsVar _ (L l v))
= do { dflags <- getDynFlags
@@ -355,8 +355,8 @@ rnExpr (HsVar _ (L l v))
rnExpr (HsIPVar x v)
= return (HsIPVar x v, emptyFVs)
-rnExpr (HsUnboundVar _ v)
- = return (HsUnboundVar noExtField v, emptyFVs)
+rnExpr (HsHole _)
+ = return (XExpr (HsUnboundVarRn (mkUnqual varName (fsLit "_"))), emptyFVs)
-- HsOverLabel: see Note [Handling overloaded and rebindable constructs]
rnExpr (HsOverLabel src v)
@@ -862,8 +862,8 @@ See #18151.
Note [Reporting unbound names]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Faced with an out-of-scope `RdrName` there are two courses of action
-A. Report an error immediately (and return a HsUnboundVar). This will halt GHC after the renamer is complete
-B. Return a HsUnboundVar without reporting an error. That will allow the typechecker to run, which in turn
+A. Report an error immediately (and return a HsUnboundVarRn). This will halt GHC after the renamer is complete
+B. Return a HsUnboundVarRn without reporting an error. That will allow the typechecker to run, which in turn
can give a better error message, notably giving the type of the variable via the "typed holes" mechanism.
When `-fdefer-out-of-scope-variables` is on we follow plan B.
=====================================
compiler/GHC/Rename/HsType.hs
=====================================
@@ -1431,10 +1431,10 @@ data NegationHandling = ReassociateNegation | KeepNegationIntact
----------------------------
get_op :: LHsExpr GhcRn -> OpName
--- An unbound name could be either HsVar or HsUnboundVar
+-- An unbound name could be either HsVar or (XExpr (HsUnboundVarRn uv))
-- See GHC.Rename.Expr.rnUnboundVar
get_op (L _ (HsVar _ n)) = NormalOp (unLoc n)
-get_op (L _ (HsUnboundVar _ uv)) = UnboundOp uv
+get_op (L _ (XExpr (HsUnboundVarRn uv))) = UnboundOp uv
get_op (L _ (HsRecSel _ fld)) = RecFldOp fld
get_op other = pprPanic "get_op" (ppr other)
=====================================
compiler/GHC/Rename/Module.hs
=====================================
@@ -1299,7 +1299,7 @@ badRuleLhsErr name lhs bad_e
= TcRnIllegalRuleLhs errReason name lhs bad_e
where
errReason = case bad_e of
- HsUnboundVar _ uv ->
+ XExpr (HsUnboundVarRn uv) ->
UnboundVariable uv $ notInScopeErr WL_Global uv
_ -> IllegalExpression
=====================================
compiler/GHC/Tc/Errors.hs
=====================================
@@ -1550,7 +1550,7 @@ maybeAddDeferredBindings ctxt hole report = do
when (deferringAnyBindings ctxt) $ do
err_tm <- mkErrorTerm ctxt (hole_loc hole) ref_ty report
-- NB: ref_ty, not hole_ty. hole_ty might be rewritten.
- -- See Note [Holes] in GHC.Tc.Types.Constraint
+ -- See Note [Holes in expressions] in GHC.Tc.Types.Constraint
writeMutVar ref err_tm
_ -> pure ()
=====================================
compiler/GHC/Tc/Gen/App.hs
=====================================
@@ -220,7 +220,7 @@ A "head" has three special cases (for which we can infer a polytype
using tcInferAppHead_maybe); otherwise is just any old expression (for
which we can infer a rho-type (via tcInfer).
-There is no special treatment for HsUnboundVar, HsOverLit etc, because
+There is no special treatment for HsUnboundVarTc, HsOverLit etc, because
we can't get a polytype from them.
Left and right sections (e.g. (x +) and (+ x)) are not yet supported.
@@ -674,7 +674,7 @@ tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args
fun_is_out_of_scope -- See Note [VTA for out-of-scope functions]
= case tc_fun of
- HsUnboundVar {} -> True
+ XExpr (HsUnboundVarTc {}) -> True
_ -> False
inst_fun :: [HsExprArg 'TcpRn] -> ForAllTyFlag -> Bool
@@ -1050,7 +1050,7 @@ expr_to_type earg =
= do { t <- go (L l e)
; let splice_result' = HsUntypedSpliceTop finalizers t
; return (L l (HsSpliceTy splice_result' splice)) }
- go (L l (HsUnboundVar _ rdr))
+ go (L l (XExpr (HsUnboundVarRn rdr)))
| isUnderscore occ = return (L l (HsWildCardTy noExtField))
| startsWithUnderscore occ =
-- See Note [Wildcards in the T2T translation]
@@ -1122,7 +1122,7 @@ This conversion is in the TcM monad because
vfun [x | x <- xs] Can't convert list comprehension to a type
vfun (\x -> x) Can't convert a lambda to a type
* It needs to check for LangExt.NamedWildCards to generate an appropriate
- error message for HsUnboundVar.
+ error message for HsUnboundVarRn.
vfun _a Not in scope: ‘_a’
(NamedWildCards disabled)
vfun _a Illegal named wildcard in a required type argument: ‘_a’
@@ -1473,7 +1473,7 @@ Note [VTA for out-of-scope functions]
Suppose 'wurble' is not in scope, and we have
(wurble @Int @Bool True 'x')
-Then the renamer will make (HsUnboundVar "wurble") for 'wurble',
+Then the renamer will make (HsUnboundVarRn "wurble") for 'wurble',
and the typechecker will typecheck it with tcUnboundId, giving it
a type 'alpha', and emitting a deferred Hole constraint, to
be reported later.
@@ -1488,7 +1488,7 @@ tcUnboundId. It later reports 'wurble' as out of scope, and tries to
give its type.
Fortunately in tcInstFun we still have access to the function, so we
-can check if it is a HsUnboundVar. We use this info to simply skip
+can check if it is a HsUnboundVarTc. We use this info to simply skip
over any visible type arguments. We'll /already/ have emitted a
Hole constraint; failing preserves that constraint.
=====================================
compiler/GHC/Tc/Gen/Expr.hs
=====================================
@@ -304,17 +304,6 @@ tcExpr e@(HsOverLit _ lit) res_ty
Just lit' -> return (HsOverLit noExtField lit')
Nothing -> tcApp e res_ty }
--- Typecheck an occurrence of an unbound Id
---
--- Some of these started life as a true expression hole "_".
--- Others might simply be variables that accidentally have no binding site
-tcExpr (HsUnboundVar _ occ) res_ty
- = do { ty <- expTypeToType res_ty -- Allow Int# etc (#12531)
- ; her <- emitNewExprHole occ ty
- ; tcEmitBindingUsage bottomUE -- Holes fit any usage environment
- -- (#18491)
- ; return (HsUnboundVar her occ) }
-
tcExpr e@(HsLit x lit) res_ty
= do { let lit_ty = hsLitType lit
; tcWrapResult e (HsLit x (convertLit lit)) lit_ty res_ty }
@@ -700,6 +689,7 @@ tcExpr (HsUntypedSplice splice _) res_ty
tcExpr (HsOverLabel {}) ty = pprPanic "tcExpr:HsOverLabel" (ppr ty)
tcExpr (SectionL {}) ty = pprPanic "tcExpr:SectionL" (ppr ty)
tcExpr (SectionR {}) ty = pprPanic "tcExpr:SectionR" (ppr ty)
+tcExpr (HsHole {}) ty = pprPanic "tcExpr:HsHole" (ppr ty)
{-
@@ -739,6 +729,17 @@ tcXExpr xe@(ExpandedThingRn o e') res_ty
= setSrcSpanA loc $
mkExpandedStmtTc ls <$> tcApp (XExpr xe) res_ty
+-- Typecheck an occurrence of an unbound Id
+--
+-- Some of these started life as a true expression hole "_".
+-- Others might simply be variables that accidentally have no binding site.
+tcXExpr (HsUnboundVarRn occ) res_ty
+ = do { ty <- expTypeToType res_ty -- Allow Int# etc (#12531)
+ ; her <- emitNewExprHole occ ty
+ ; tcEmitBindingUsage bottomUE -- Holes fit any usage environment
+ -- (#18491)
+ ; return (XExpr (HsUnboundVarTc her occ)) }
+
tcXExpr xe res_ty = tcApp (XExpr xe) res_ty
{-
=====================================
compiler/GHC/Tc/Gen/Head.hs
=====================================
@@ -1281,9 +1281,9 @@ addStmtCtxt stmt thing_inside
addExprCtxt :: HsExpr GhcRn -> TcRn a -> TcRn a
addExprCtxt e thing_inside
= case e of
- HsUnboundVar {} -> thing_inside
+ XExpr (HsUnboundVarRn {}) -> thing_inside
_ -> addErrCtxt (exprCtxt e) thing_inside
- -- The HsUnboundVar special case addresses situations like
+ -- The HsUnboundVarRn special case addresses situations like
-- f x = _
-- when we don't want to say "In the expression: _",
-- because it is mentioned in the error message itself
=====================================
compiler/GHC/Tc/Types/Constraint.hs
=====================================
@@ -370,7 +370,7 @@ data DelayedError
= DE_Hole Hole
-- ^ A hole (in a type or in a term).
--
- -- See Note [Holes].
+ -- See Note [Holes in expressions].
| DE_NotConcrete NotConcreteError
-- ^ A type could not be ensured to be concrete.
--
@@ -383,7 +383,7 @@ instance Outputable DelayedError where
-- | A hole stores the information needed to report diagnostics
-- about holes in terms (unbound identifiers or underscores) or
-- in types (also called wildcards, as used in partial type
--- signatures). See Note [Holes].
+-- signatures). See Note [Holes in expressions] for holes in terms.
data Hole
= Hole { hole_sort :: HoleSort -- ^ What flavour of hole is this?
, hole_occ :: RdrName -- ^ The name of this hole
@@ -673,43 +673,78 @@ of the rhs. This is necessary because these constraints are used for substitutio
during solving. If the kinds differed, then the substitution would take a well-kinded
type to an ill-kinded one.
-Note [Holes]
-~~~~~~~~~~~~
-This Note explains how GHC tracks *holes*.
-
-A hole represents one of two conditions:
- - A missing bit of an expression. Example: foo x = x + _
- - A missing bit of a type. Example: bar :: Int -> _
-
-What these have in common is that both cause GHC to emit a diagnostic to the
-user describing the bit that is left out.
-
-When a hole is encountered, a new entry of type Hole is added to the ambient
-WantedConstraints. The type (hole_ty) of the hole is then simplified during
-solving (with respect to any Givens in surrounding implications). It is
-reported with all the other errors in GHC.Tc.Errors.
-
-For expression holes, the user has the option of deferring errors until runtime
-with -fdefer-type-errors. In this case, the hole actually has evidence: this
-evidence is an erroring expression that prints an error and crashes at runtime.
-The ExprHole variant of holes stores an IORef EvTerm that will contain this evidence;
-during constraint generation, this IORef was stored in the HsUnboundVar extension
-field by the type checker. The desugarer simply dereferences to get the CoreExpr.
-
-Prior to fixing #17812, we used to invent an Id to hold the erroring
-expression, and then bind it during type-checking. But this does not support
-representation-polymorphic out-of-scope identifiers. See
-typecheck/should_compile/T17812. We thus use the mutable-CoreExpr approach
-described above.
-
-You might think that the type in the HoleExprRef is the same as the type of the
-hole. However, because the hole type (hole_ty) is rewritten with respect to
-givens, this might not be the case. That is, the hole_ty is always (~) to the
-type of the HoleExprRef, but they might not be `eqType`. We need the type of the generated
-evidence to match what is expected in the context of the hole, and so we must
-store these types separately.
-
-Type-level holes have no evidence at all.
+Note [Holes in expressions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This Note explains how GHC tracks "holes" in expressions. It does not
+deal with holes in types, nor with partial type signatures.
+
+A hole represents a missing bit of an expression. Example:
+ foo x = x && _
+GHC then emits a diagnostic, describing the bit that is left out:
+ Foo.hs:5:14: error: [GHC-88464]
+ • Found hole: _ :: Bool
+ • In the second argument of ‘(&&)’, namely ‘_’
+ In the expression: x && _
+
+GHC uses the same mechanism is used to give diagnostics for out-of-scope
+variables:
+ foo x = x && y
+gives diagnostic
+ Foo.hs:5:14: error: [GHC-88464]
+ Variable not in scope: y :: Bool
+
+Here is how holes are represented in expressions:
+
+* If the user wrote "_":
+ Parser HsHole
+ Renamer XExpr (HsUnboundVarRn "_")
+ Typechecker XExpr (HsUnboundVarTc ref "_")
+
+* If the user wrote "x", where `x` is not in scope
+ Parser HsVar "x"
+ Renamer XExpr (HsUnboundVarRn "x")
+ Typechecker XExpr (HsUnboundVarTc ref "x")
+
+In both cases (ref::HoleExprRef) contains
+ - The type of the hole.
+ - A ref-cell that is filled in (by the typechecker) with an
+ error thunk. With -fdefer-type errors we use this as the
+ value of the hole.
+ - A Unique (see Note [Uniques and tags]).
+
+Typechecking holes
+
+* When the typechecker encounters a `HsUnboundVarRn`, it returns
+ a `HsUnboundVarTc`, but also emits a `DelayedError` into the `WantedConstraints`.
+
+* This DelayedError later triggers the error reporting, and the filling-in of
+ the error thunk, in GHC.Tc.Errors.
+
+* The user has the option of deferring errors until runtime with
+ `-fdefer-type-errors`. In this case, the hole carries evidence in its
+ `HoleExprRef`. This evidence is an erroring expression that prints an error
+ and crashes at runtime.
+
+Desugaring holes
+
+* During desugaring, the `(HsExpr (HsUnboundVarTc ref "x"))` is desugared by
+ reading the ref-cell to find the error thunk evidence term, put there by the
+ constraint solver.
+
+Wrinkles:
+
+* Prior to fixing #17812, we used to invent an Id to hold the erroring
+ expression, and then bind it during type-checking. But this does not support
+ representation-polymorphic out-of-scope identifiers. See
+ typecheck/should_compile/T17812. We thus use the mutable-CoreExpr approach
+ described above.
+
+* You might think that the type in the HoleExprRef is the same as the type of the
+ hole. However, because the hole type (hole_ty) is rewritten with respect to
+ givens, this might not be the case. That is, the hole_ty is always (~) to the
+ type of the HoleExprRef, but they might not be `eqType`. We need the type of the generated
+ evidence to match what is expected in the context of the hole, and so we must
+ store these types separately.
-}
mkNonCanonical :: CtEvidence -> Ct
=====================================
compiler/GHC/Tc/Types/Evidence.hs
=====================================
@@ -594,7 +594,7 @@ data EvCallStack
-}
-- | Where to store evidence for expression holes
--- See Note [Holes] in GHC.Tc.Types.Constraint
+-- See Note [Holes in expressions] in GHC.Tc.Types.Constraint
data HoleExprRef = HER (IORef EvTerm) -- ^ where to write the erroring expression
TcType -- ^ expected type of that expression
Unique -- ^ for debug output only
=====================================
compiler/GHC/Tc/Types/Origin.hs
=====================================
@@ -717,7 +717,6 @@ lexprCtOrigin (L _ e) = exprCtOrigin e
exprCtOrigin :: HsExpr GhcRn -> CtOrigin
exprCtOrigin (HsVar _ (L _ name)) = OccurrenceOf name
exprCtOrigin (HsGetField _ _ (L _ f)) = HasFieldOrigin (field_label $ unLoc $ dfoLabel f)
-exprCtOrigin (HsUnboundVar {}) = Shouldn'tHappenOrigin "unbound variable"
exprCtOrigin (HsRecSel _ f) = OccurrenceOfRecSel (unLoc $ foLabel f)
exprCtOrigin (HsOverLabel _ l) = OverLabelOrigin l
exprCtOrigin (ExplicitList {}) = ListOrigin
@@ -752,12 +751,14 @@ exprCtOrigin (HsUntypedSplice {}) = Shouldn'tHappenOrigin "TH untyped splice"
exprCtOrigin (HsProc {}) = Shouldn'tHappenOrigin "proc"
exprCtOrigin (HsStatic {}) = Shouldn'tHappenOrigin "static expression"
exprCtOrigin (HsEmbTy {}) = Shouldn'tHappenOrigin "type expression"
+exprCtOrigin (HsHole {}) = Shouldn'tHappenOrigin "hole expression"
exprCtOrigin (HsForAll {}) = Shouldn'tHappenOrigin "forall telescope" -- See Note [Types in terms]
exprCtOrigin (HsQual {}) = Shouldn'tHappenOrigin "constraint context" -- See Note [Types in terms]
exprCtOrigin (HsFunArr {}) = Shouldn'tHappenOrigin "function arrow" -- See Note [Types in terms]
exprCtOrigin (XExpr (ExpandedThingRn thing _)) | OrigExpr a <- thing = exprCtOrigin a
| OrigStmt _ <- thing = DoOrigin
| OrigPat p <- thing = DoPatOrigin p
+exprCtOrigin (XExpr (HsUnboundVarRn {})) = Shouldn'tHappenOrigin "unbound variable"
exprCtOrigin (XExpr (PopErrCtxt {})) = Shouldn'tHappenOrigin "PopErrCtxt"
-- | Extract a suitable CtOrigin from a MatchGroup
=====================================
compiler/GHC/Tc/Zonk/Type.hs
=====================================
@@ -925,9 +925,9 @@ zonkExpr (HsVar x (L l id))
do { id' <- zonkIdOcc id
; return (HsVar x (L l id')) }
-zonkExpr (HsUnboundVar her occ)
+zonkExpr (XExpr (HsUnboundVarTc her occ))
= do her' <- zonk_her her
- return (HsUnboundVar her' occ)
+ return (XExpr (HsUnboundVarTc her' occ))
where
zonk_her :: HoleExprRef -> ZonkTcM HoleExprRef
zonk_her (HER ref ty u)
@@ -1079,6 +1079,7 @@ zonkExpr (HsEmbTy x _) = dataConCantHappen x
zonkExpr (HsQual x _ _) = dataConCantHappen x
zonkExpr (HsForAll x _ _) = dataConCantHappen x
zonkExpr (HsFunArr x _ _ _) = dataConCantHappen x
+zonkExpr (HsHole x) = dataConCantHappen x
zonkExpr (XExpr (WrapExpr (HsWrap co_fn expr)))
= runZonkBndrT (zonkCoFn co_fn) $ \ new_co_fn ->
=====================================
compiler/Language/Haskell/Syntax/Expr.hs
=====================================
@@ -41,7 +41,6 @@ import Data.Bool
import Data.Eq
import Data.Maybe
import Data.List.NonEmpty ( NonEmpty )
-import GHC.Types.Name.Reader
{- Note [RecordDotSyntax field updates]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -338,19 +337,6 @@ data HsExpr p
= HsVar (XVar p)
(LIdP p) -- ^ Variable
-- See Note [Located RdrNames]
-
- | HsUnboundVar (XUnboundVar p)
- RdrName -- ^ Unbound variable; also used for "holes"
- -- (_ or _x).
- -- Turned from HsVar to HsUnboundVar by the
- -- renamer, when it finds an out-of-scope
- -- variable or hole.
- -- The (XUnboundVar p) field becomes an HoleExprRef
- -- after typechecking; this is where the
- -- erroring expression will be written after
- -- solving. See Note [Holes] in GHC.Tc.Types.Constraint.
-
-
| HsRecSel (XRecSel p)
(FieldOcc p) -- ^ Variable pointing to record selector
-- See Note [Non-overloaded record field selectors] and
@@ -404,7 +390,7 @@ data HsExpr p
-- NB Bracketed ops such as (+) come out as Vars.
-- NB Sadly, we need an expr for the operator in an OpApp/Section since
- -- the renamer may turn a HsVar into HsRecSel or HsUnboundVar
+ -- the renamer may turn a HsVar into HsRecSel or HsUnboundVarRn
| OpApp (XOpApp p)
(LHsExpr p) -- left operand
@@ -651,6 +637,10 @@ data HsExpr p
| HsEmbTy (XEmbTy p)
(LHsWcType (NoGhcTc p))
+ -- | Holes in expressions.
+ -- See Note [Holes in expressions] in GHC.Tc.Types.Constraint.
+ | HsHole (XHole p)
+
-- | Forall-types @forall tvs. t@ and @forall tvs -> t at .
-- Used with @RequiredTypeArguments@, e.g. @fn (forall a. Proxy a)@.
-- See Note [Types in terms]
=====================================
compiler/Language/Haskell/Syntax/Extension.hs
=====================================
@@ -448,6 +448,7 @@ type family XTick x
type family XBinTick x
type family XPragE x
type family XEmbTy x
+type family XHole x
type family XForAll x
type family XQual x
type family XFunArr x
=====================================
testsuite/tests/perf/compiler/hard_hole_fits.hs
=====================================
@@ -12,7 +12,7 @@ import GHC (GhcPs)
testMe :: HsExpr GhcPs -> Int
testMe (HsVar a b) = _
-testMe (HsUnboundVar xuv uv) = _
+testMe (HsHole a) = _
testMe (HsOverLabel xol m_ip) = _
testMe (HsIPVar xv hin) = _
testMe (HsOverLit xole hol) = _
=====================================
testsuite/tests/perf/compiler/hard_hole_fits.stderr
=====================================
@@ -17,14 +17,12 @@ hard_hole_fits.hs:14:22: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
(imported from ‘Prelude’ at hard_hole_fits.hs:8:8-20
(and originally defined in ‘GHC.Internal.Enum’))
-hard_hole_fits.hs:15:32: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
- • Found hole: _ :: Int
- • In an equation for ‘testMe’: testMe (HsUnboundVar xuv uv) = _
- • Relevant bindings include
- uv :: GHC.Types.Name.Reader.RdrName
- (bound at hard_hole_fits.hs:15:26)
- xuv :: Language.Haskell.Syntax.Extension.XUnboundVar GhcPs
- (bound at hard_hole_fits.hs:15:22)
+hard_hole_fits.hs:15:21: warning: [GHC-88464] [-Wtyped-holes (in -Wdefault)]
+ Found hole: _ :: Int
+ In an equation for ‘testMe’: testMe (HsHole a) = _
+ Relevant bindings include
+ a :: Language.Haskell.Syntax.Extension.XHole GhcPs
+ (bound at hard_hole_fits.hs:15:16)
testMe :: HsExpr GhcPs -> Int (bound at hard_hole_fits.hs:14:1)
Valid hole fits include
maxBound :: forall a. Bounded a => a
=====================================
testsuite/tests/plugins/T20803-plugin/FixErrorsPlugin.hs
=====================================
@@ -20,15 +20,15 @@ import Data.Maybe
plugin :: Plugin
plugin = defaultPlugin {parsedResultAction = parsedAction}
--- Replace every hole (and other unbound vars) with the given expression
+-- Replace every hole with the given expression
replaceHoles :: forall a . Data a => HsExpr GhcPs -> a -> a
replaceHoles new = gmapT \case
(d :: d) -> replaceHoles new d `fromMaybe` tryHole
where
tryHole :: Maybe d
tryHole = eqT @d @(HsExpr GhcPs) >>= \case
- Eq.Refl | HsUnboundVar _ _ <- d -> Just new
- _ -> Nothing
+ Eq.Refl | HsHole _ <- d -> Just new
+ _ -> Nothing
parsedAction :: [CommandLineOption] -> ModSummary
-> ParsedResult -> Hsc ParsedResult
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -329,7 +329,7 @@ instance HasTrailing AnnExplicitSum where
trailing _ = []
setTrailing a _ = a
-instance HasTrailing (Maybe EpAnnUnboundVar) where
+instance HasTrailing (Maybe EpAnnHole) where
trailing _ = []
setTrailing a _ = a
@@ -3042,16 +3042,16 @@ instance ExactPrint (HsExpr GhcPs) where
then markAnnotated n
else return n
return (HsVar x n')
- exact (HsUnboundVar an n) = do
+ exact x@(HsHole an) = do
case an of
- Just (EpAnnUnboundVar (ob,cb) l) -> do
- ob' <- printStringAtAA ob "`"
+ Just (EpAnnHole (ob,cb) l) -> do
+ ob' <- printStringAtAA ob "`"
l' <- printStringAtAA l "_"
cb' <- printStringAtAA cb "`"
- return (HsUnboundVar (Just (EpAnnUnboundVar (ob',cb') l')) n)
- _ -> do
- printStringAdvanceA "_" >> return ()
- return (HsUnboundVar an n)
+ return (HsHole (Just (EpAnnHole (ob',cb') l')))
+ Nothing -> do
+ printStringAdvanceA "_"
+ return x
exact x@(HsOverLabel src l) = do
printStringAdvanceA "#" >> return ()
case src of
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7ed954d99ef1a3f3798630bb46d08b404567e9d1
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7ed954d99ef1a3f3798630bb46d08b404567e9d1
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240913/155550ae/attachment-0001.html>
More information about the ghc-commits
mailing list