[Git][ghc/ghc][wip/T24464] Improve desugaring for pattern matching
Simon Peyton Jones pushed to branch wip/T24464 at Glasgow Haskell Compiler / GHC Commits: e3b52739 by Simon Peyton Jones at 2026-01-29T00:08:38+00:00 Improve desugaring for pattern matching ...to avoid pattern match checking when we don't need it, and to avoid emitting static pointers twice - - - - - 8 changed files: - compiler/GHC/HsToCore/Expr.hs - compiler/GHC/HsToCore/GuardedRHSs.hs - compiler/GHC/HsToCore/Match.hs - compiler/GHC/HsToCore/Monad.hs - compiler/GHC/HsToCore/Pmc.hs - compiler/GHC/HsToCore/Types.hs - compiler/GHC/Tc/Gen/Bind.hs - compiler/GHC/Tc/Utils/Env.hs Changes: ===================================== compiler/GHC/HsToCore/Expr.hs ===================================== @@ -29,6 +29,7 @@ import GHC.HsToCore.Utils import GHC.HsToCore.Arrows import GHC.HsToCore.Monad import GHC.HsToCore.Pmc +import GHC.HsToCore.Types( LdiNablas(..) ) import GHC.HsToCore.Pmc.Utils import GHC.HsToCore.Errors.Types import GHC.HsToCore.Quote @@ -505,7 +506,12 @@ dsExpr (HsStatic (static_ptr_ty, from_static_fun) expr@(L loc _)) ; static_id <- newStaticId (mkSpecForAllTys static_fvs static_ptr_ty) - ; emitStaticBinds [(static_id, static_rhs)] + -- Emit the static bindings to top level, but NOT when we are in + -- the auxiliary desugaring for the pattern-match checking + ; ldi_nablas <- getPmNablas + ; case ldi_nablas of + NoPmc -> return () + Ldi {} -> emitStaticBinds [(static_id, static_rhs)] ; return (App from_static_ds (mkVarApps (Var static_id) static_fvs)) } ===================================== compiler/GHC/HsToCore/GuardedRHSs.hs ===================================== @@ -22,7 +22,7 @@ import GHC.Core.Utils (bindNonRec) import GHC.HsToCore.Monad import GHC.HsToCore.Utils -import GHC.HsToCore.Pmc.Types ( Nablas ) +import GHC.HsToCore.Types import GHC.Core.Type ( Type ) import GHC.Types.SrcLoc import GHC.Utils.Outputable @@ -44,7 +44,7 @@ producing an expression with a runtime error in the corner case if necessary. The type argument gives the type of the @ei@. -} -dsGuarded :: GRHSs GhcTc (LHsExpr GhcTc) -> Type -> NonEmpty Nablas -> DsM CoreExpr +dsGuarded :: GRHSs GhcTc (LHsExpr GhcTc) -> Type -> NonEmpty LdiNablas -> DsM CoreExpr dsGuarded grhss rhs_ty rhss_nablas = do match_result <- dsGRHSs PatBindRhs grhss rhs_ty rhss_nablas error_expr <- mkErrorAppDs nON_EXHAUSTIVE_GUARDS_ERROR_ID rhs_ty @@ -56,7 +56,7 @@ dsGuarded grhss rhs_ty rhss_nablas = do dsGRHSs :: HsMatchContextRn -> GRHSs GhcTc (LHsExpr GhcTc) -- ^ Guarded RHSs -> Type -- ^ Type of RHS - -> NonEmpty Nablas -- ^ Refined pattern match checking + -> NonEmpty LdiNablas -- ^ Refined pattern match checking -- models, one for the pattern part and -- one for each GRHS. -> DsM (MatchResult CoreExpr) @@ -73,11 +73,11 @@ dsGRHSs hs_ctx (GRHSs _ grhss binds) rhs_ty rhss_nablas -- NB: nested dsLet inside matchResult ; return match_result2 } -dsGRHS :: HsMatchContextRn -> Type -> Nablas -> LGRHS GhcTc (LHsExpr GhcTc) +dsGRHS :: HsMatchContextRn -> Type -> LdiNablas -> LGRHS GhcTc (LHsExpr GhcTc) -> DsM (MatchResult CoreExpr) dsGRHS hs_ctx rhs_ty rhs_nablas (L _ (GRHS _ guards rhs)) = updPmNablas rhs_nablas $ - matchGuards (map unLoc guards) hs_ctx rhs rhs_ty + matchGuards (map unLoc guards) hs_ctx rhs rhs_ty {- ************************************************************************ ===================================== compiler/GHC/HsToCore/Match.hs ===================================== @@ -39,7 +39,7 @@ import GHC.Tc.Types.Evidence import GHC.Tc.Utils.Monad import GHC.HsToCore.Pmc import GHC.HsToCore.Pmc.Utils -import GHC.HsToCore.Pmc.Types ( Nablas ) +import GHC.HsToCore.Types ( LdiNablas ) import GHC.HsToCore.Monad import GHC.HsToCore.Binds import GHC.HsToCore.GuardedRHSs @@ -833,7 +833,9 @@ matchWrapper ctxt scrs (MG { mg_alts = L _ matches ; return (new_vars, result_expr) } where -- Called once per equation in the match, or alternative in the case - mk_eqn_info :: LMatch GhcTc (LHsExpr GhcTc) -> (Nablas, NonEmpty Nablas) -> DsM EquationInfo + mk_eqn_info :: LMatch GhcTc (LHsExpr GhcTc) + -> (LdiNablas, NonEmpty LdiNablas) + -> DsM EquationInfo mk_eqn_info (L _ (Match { m_pats = L _ pats, m_grhss = grhss })) (pat_nablas, rhss_nablas) = do { dflags <- getDynFlags ; let upats = map (decideBangHood dflags) pats @@ -850,13 +852,6 @@ matchWrapper ctxt scrs (MG { mg_alts = L _ matches then id else discardWarningsDs - initNablasMatches :: Nablas -> [LMatch GhcTc b] -> [(Nablas, NonEmpty Nablas)] - initNablasMatches ldi_nablas ms - = map (\(L _ m) -> (ldi_nablas, initNablasGRHSs ldi_nablas (m_grhss m))) ms - - initNablasGRHSs :: Nablas -> GRHSs GhcTc b -> NonEmpty Nablas - initNablasGRHSs ldi_nablas m = ldi_nablas <$ grhssGRHSs m - {- Note [Long-distance information in matchWrapper] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The pattern match checking in matchWrapper is done conditionally, depending @@ -985,7 +980,7 @@ matchSinglePatVar var mb_scrut ctx pat ty match_result ; match [var] ty [eqn_info] } -updPmNablasMatchResult :: Nablas -> MatchResult r -> MatchResult r +updPmNablasMatchResult :: LdiNablas -> MatchResult r -> MatchResult r updPmNablasMatchResult nablas = \case MR_Infallible body_fn -> MR_Infallible $ updPmNablas nablas body_fn ===================================== compiler/GHC/HsToCore/Monad.hs ===================================== @@ -65,7 +65,7 @@ import GHC.Hs import GHC.HsToCore.Types import GHC.HsToCore.Errors.Types -import GHC.HsToCore.Pmc.Solver.Types (Nablas, initNablas) +import GHC.HsToCore.Pmc.Solver.Types (initNablas) import GHC.Core.FamInstEnv import GHC.Core @@ -416,7 +416,7 @@ mkDsEnvs unit_env mod rdr_env type_env fam_inst_env ptc msg_var cc_st_var } lcl_env = DsLclEnv { dsl_meta = emptyNameEnv , dsl_loc = real_span - , dsl_nablas = initNablas + , dsl_nablas = Ldi initNablas , dsl_unspecables = Just emptyVarSet } in (gbl_env, lcl_env) @@ -479,12 +479,12 @@ getGhcModeDs :: DsM GhcMode getGhcModeDs = getDynFlags >>= return . ghcMode -- | Get the current pattern match oracle state. See 'dsl_nablas'. -getPmNablas :: DsM Nablas +getPmNablas :: DsM LdiNablas getPmNablas = do { env <- getLclEnv; return (dsl_nablas env) } -- | Set the pattern match oracle state within the scope of the given action. -- See 'dsl_nablas'. -updPmNablas :: Nablas -> DsM a -> DsM a +updPmNablas :: LdiNablas -> DsM a -> DsM a updPmNablas nablas = updLclEnv (\env -> env { dsl_nablas = nablas }) addUnspecables :: [EvVar] -> DsM a -> DsM a ===================================== compiler/GHC/HsToCore/Pmc.hs ===================================== @@ -30,6 +30,7 @@ module GHC.HsToCore.Pmc ( -- Checking and printing pmcPatBind, pmcMatches, pmcGRHSs, pmcRecSel, + initNablasMatches, isMatchContextPmChecked, isMatchContextPmChecked_SinglePat, -- See Note [Long-distance information] @@ -45,6 +46,7 @@ import GHC.HsToCore.Pmc.Utils import GHC.HsToCore.Pmc.Desugar import GHC.HsToCore.Pmc.Check import GHC.HsToCore.Pmc.Solver +import GHC.HsToCore.Types import GHC.Types.Basic (Origin(..), isDoExpansionGenerated) import GHC.Core import GHC.Driver.DynFlags @@ -77,26 +79,35 @@ import GHC.Tc.Utils.Monad -- capturing long-distance information, or the trivially habitable 'Nablas' if -- the former is uninhabited. -- See Note [Recovering from unsatisfiable pattern-matching constraints]. -getLdiNablas :: DsM Nablas +getLdiNablas :: DsM LdiNablas getLdiNablas = do nablas <- getPmNablas - isInhabited nablas >>= \case - True -> pure nablas - False -> pure initNablas + case nablas of + NoPmc -> pure NoPmc + Ldi nablas -> isInhabited nablas >>= \case + True -> pure (Ldi nablas) + False -> pure (Ldi initNablas) -- | We need to call the Hs desugarer to get the Core of a let-binding or where -- clause. We don't want to run the coverage checker when doing so! Efficiency -- is one concern, but also a lack of properly set up long-distance information -- might trigger warnings that we normally wouldn't emit. -noCheckDs :: DsM a -> DsM a -noCheckDs = updTopFlags (\dflags -> foldl' wopt_unset dflags allPmCheckWarnings) +dontDoPmc :: DsM a -> DsM a +dontDoPmc thing_inside = updPmNablas NoPmc thing_inside + +whenDoingPmc :: a -> (Nablas -> DsM a) -> DsM a +whenDoingPmc no_pmc thing_inside + = do { ldi_nablas <- getPmNablas + ; case ldi_nablas of + NoPmc -> return no_pmc + Ldi nablas -> thing_inside nablas } -- | Check a pattern binding (let, where) for exhaustiveness. -pmcPatBind :: DsMatchContext -> Id -> Pat GhcTc -> DsM Nablas +pmcPatBind :: DsMatchContext -> Id -> Pat GhcTc -> DsM LdiNablas pmcPatBind ctxt@(DsMatchContext match_ctxt loc) var p - = mb_discard_warnings $ do - !missing <- getLdiNablas - pat_bind <- noCheckDs $ desugarPatBind loc var p + = whenDoingPmc NoPmc $ \ !missing -> + mb_discard_warnings $ do + pat_bind <- dontDoPmc $ desugarPatBind loc var p tracePm "pmcPatBind {" (vcat [ppr ctxt, ppr var, ppr p, ppr pat_bind, ppr missing]) result <- unCA (checkPatBind pat_bind) missing let ldi = ldiGRHS $ ( \ pb -> case pb of PmPatBind grhs -> grhs) $ cr_ret result @@ -124,21 +135,21 @@ pmcPatBind ctxt@(DsMatchContext match_ctxt loc) var p pmcGRHSs :: HsMatchContextRn -- ^ Match context, for warning messages -> GRHSs GhcTc (LHsExpr GhcTc) -- ^ The GRHSs to check - -> DsM (NonEmpty Nablas) -- ^ Covered 'Nablas' for each RHS, for long - -- distance info -pmcGRHSs hs_ctxt guards@(GRHSs _ grhss _) = do - let combined_loc = foldl1 combineSrcSpans (NE.map getLocA grhss) - ctxt = DsMatchContext hs_ctxt combined_loc - !missing <- getLdiNablas - matches <- noCheckDs $ desugarGRHSs combined_loc empty guards - tracePm "pmcGRHSs" (hang (vcat [ppr ctxt - , text "Guards:"]) - 2 - (pprGRHSs hs_ctxt guards $$ ppr missing)) - result <- unCA (checkGRHSs matches) missing - tracePm "}: " (ppr (cr_uncov result)) - formatReportWarnings ReportGRHSs ctxt [] result - return (ldiGRHSs (cr_ret result)) + -> DsM (NonEmpty LdiNablas) -- ^ Covered 'Nablas' for each RHS, + -- for long distance info +pmcGRHSs hs_ctxt guards@(GRHSs _ grhss _) = + whenDoingPmc (NE.map (const NoPmc) grhss) $ \ !missing -> do + let combined_loc = foldl1 combineSrcSpans (NE.map getLocA grhss) + ctxt = DsMatchContext hs_ctxt combined_loc + matches <- dontDoPmc $ desugarGRHSs combined_loc empty guards + tracePm "pmcGRHSs" (hang (vcat [ppr ctxt + , text "Guards:"]) + 2 + (pprGRHSs hs_ctxt guards $$ ppr missing)) + result <- unCA (checkGRHSs matches) missing + tracePm "}: " (ppr (cr_uncov result)) + formatReportWarnings ReportGRHSs ctxt [] result + return (ldiGRHSs (cr_ret result)) -- | Check a list of syntactic 'Match'es (part of case, functions, etc.), each -- with a 'Pat' and one or more 'GRHSs': @@ -160,37 +171,44 @@ pmcMatches -> DsMatchContext -- ^ Match context, for warnings messages -> [Id] -- ^ Match variables, i.e. x and y above -> [LMatch GhcTc (LHsExpr GhcTc)] -- ^ List of matches - -> DsM [(Nablas, NonEmpty Nablas)] -- ^ One covered 'Nablas' per Match and - -- GRHS, for long distance info. -pmcMatches origin ctxt vars matches = {-# SCC "pmcMatches" #-} do - -- We have to force @missing@ before printing out the trace message, - -- otherwise we get interleaved output from the solver. This function - -- should be strict in @missing@ anyway! - !missing <- getLdiNablas - tracePm "pmcMatches {" $ - hang (vcat [ppr origin, ppr ctxt, ppr vars, text "Matches:"]) - 2 - ((ppr matches) $$ (text "missing:" <+> ppr missing)) - case NE.nonEmpty matches of - Nothing -> do - -- This must be an -XEmptyCase. See Note [Checking EmptyCase] - let var = only vars - empty_case <- noCheckDs $ desugarEmptyCase var - result <- unCA (checkEmptyCase empty_case) missing - tracePm "}: " (ppr (cr_uncov result)) - formatReportWarnings ReportEmptyCase ctxt vars result - return [] - Just matches -> do - matches <- {-# SCC "desugarMatches" #-} - noCheckDs $ desugarMatches vars matches - tracePm "desugared matches" (ppr matches) - result <- {-# SCC "checkMatchGroup" #-} - unCA (checkMatchGroup matches) missing - tracePm "}: " (ppr (cr_uncov result)) - unless (isDoExpansionGenerated origin) -- Do expansion generated code shouldn't emit overlapping warnings - ({-# SCC "formatReportWarnings" #-} - formatReportWarnings ReportMatchGroup ctxt vars result) - return (NE.toList (ldiMatchGroup (cr_ret result))) + -> DsM [(LdiNablas, NonEmpty LdiNablas)] -- ^ One covered 'Nablas' per Match and + -- GRHS, for long distance info. +pmcMatches origin ctxt vars matches = {-# SCC "pmcMatches" #-} + whenDoingPmc (initNablasMatches NoPmc matches) $ \ !missing -> do + -- We have to force @missing@ before printing out the trace message, + -- otherwise we get interleaved output from the solver. This function + -- should be strict in @missing@ anyway! + tracePm "pmcMatches {" $ + hang (vcat [ppr origin, ppr ctxt, ppr vars, text "Matches:"]) + 2 + ((ppr matches) $$ (text "missing:" <+> ppr missing)) + case NE.nonEmpty matches of + Nothing -> do + -- This must be an -XEmptyCase. See Note [Checking EmptyCase] + let var = only vars + empty_case <- dontDoPmc $ desugarEmptyCase var + result <- unCA (checkEmptyCase empty_case) missing + tracePm "}: " (ppr (cr_uncov result)) + formatReportWarnings ReportEmptyCase ctxt vars result + return [] + Just matches -> do + matches <- {-# SCC "desugarMatches" #-} + dontDoPmc $ desugarMatches vars matches + tracePm "desugared matches" (ppr matches) + result <- {-# SCC "checkMatchGroup" #-} + unCA (checkMatchGroup matches) missing + tracePm "}: " (ppr (cr_uncov result)) + unless (isDoExpansionGenerated origin) -- Do expansion generated code shouldn't emit overlapping warnings + ({-# SCC "formatReportWarnings" #-} + formatReportWarnings ReportMatchGroup ctxt vars result) + return (NE.toList (ldiMatchGroup (cr_ret result))) + +initNablasMatches :: LdiNablas -> [LMatch GhcTc b] -> [(LdiNablas, NonEmpty LdiNablas)] +initNablasMatches ldi_nablas ms + = map (\(L _ m) -> (ldi_nablas, initNablasGRHSs ldi_nablas (m_grhss m))) ms + where + initNablasGRHSs :: LdiNablas -> GRHSs GhcTc b -> NonEmpty LdiNablas + initNablasGRHSs ldi_nablas m = NE.map (const ldi_nablas) (grhssGRHSs m) {- Note [Detecting incomplete record selectors] @@ -361,9 +379,8 @@ pmcRecSel sel_id arg | RecSelId{ sel_cons = rec_sel_info } <- idDetails sel_id , RSI { rsi_def = cons_w_field, rsi_undef = cons_wo_field } <- rec_sel_info , not (null cons_wo_field) - = do { !missing <- getLdiNablas - - ; tracePm "pmcRecSel {" (ppr sel_id) + = whenDoingPmc () $ \ !missing -> + do { tracePm "pmcRecSel {" (ppr sel_id) ; CheckResult{ cr_ret = PmRecSel{ pr_arg_var = arg_id }, cr_uncov = uncov_nablas } <- unCA (checkRecSel (PmRecSel () arg cons_w_field)) missing ; tracePm "}: " $ ppr uncov_nablas @@ -415,18 +432,18 @@ discardWarningsDs. -- * Collecting long-distance information -- -ldiMatchGroup :: PmMatchGroup Post -> NonEmpty (Nablas, NonEmpty Nablas) +ldiMatchGroup :: PmMatchGroup Post -> NonEmpty (LdiNablas, NonEmpty LdiNablas) ldiMatchGroup (PmMatchGroup matches) = ldiMatch <$> matches -ldiMatch :: PmMatch Post -> (Nablas, NonEmpty Nablas) +ldiMatch :: PmMatch Post -> (LdiNablas, NonEmpty LdiNablas) ldiMatch (PmMatch { pm_pats = red, pm_grhss = grhss }) = - (rs_cov red, ldiGRHSs grhss) + (Ldi (rs_cov red), ldiGRHSs grhss) -ldiGRHSs :: PmGRHSs Post -> NonEmpty Nablas +ldiGRHSs :: PmGRHSs Post -> NonEmpty LdiNablas ldiGRHSs (PmGRHSs { pgs_grhss = grhss }) = ldiGRHS <$> grhss -ldiGRHS :: PmGRHS Post -> Nablas -ldiGRHS (PmGRHS { pg_grds = red }) = rs_cov red +ldiGRHS :: PmGRHS Post -> LdiNablas +ldiGRHS (PmGRHS { pg_grds = red }) = Ldi (rs_cov red) -- -- * Collecting redundancy information @@ -620,9 +637,11 @@ getNFirstUncovered mode vars n (MkNablas nablas) = go n (bagToList nablas) -- with 'unsafeInterleaveM' in order not to do unnecessary work. locallyExtendPmNablas :: DsM a -> (Nablas -> DsM Nablas) -> DsM a locallyExtendPmNablas k ext = do - nablas <- getLdiNablas - nablas' <- unsafeInterleaveM $ ext nablas - updPmNablas nablas' k + ldi_nablas <- getLdiNablas + case ldi_nablas of + NoPmc -> k -- No nablas to extend, easy! + Ldi nablas -> do { nablas' <- unsafeInterleaveM $ ext nablas + ; updPmNablas (Ldi nablas') k } -- | Add in-scope type constraints if the coverage checker might run and then -- run the given action. @@ -670,18 +689,40 @@ Consider Humans can make the "long-distance connection" between the outer pattern match and the nested case pattern match to see that the inner pattern match is -exhaustive: @c@ can't be @R@ anymore because it was matched in the first clause -of @f@. - -To achieve similar reasoning in the coverage checker, we keep track of the set -of values that can reach a particular program point (often loosely referred to -as "Covered set") in 'GHC.HsToCore.Monad.dsl_nablas'. -We fill that set with Covered Nablas returned by the exported checking -functions, which the call sites put into place with -'GHC.HsToCore.Monad.updPmNablas'. -Call sites also extend this set with facts from type-constraint dictionaries, -case scrutinees, etc. with the exported functions 'addTyCs', 'addCoreScrutTmCs' -and 'addHsScrutTmCs'. +exhaustive: `c` can't be `R` anymore because it was matched in the first clause +of `f`. + +To achieve similar reasoning in the coverage checker: + +* We keep track of the set of values that can reach a particular program point + (often loosely refer red to as "Covered set") in 'GHC.HsToCore.Monad.dsl_nablas + :: LdiNablas'. + +* We fill that set with Covered Nablas returned by the exported checking functions, + which the call sites put into place with 'GHC.HsToCore.Monad.updPmNablas'. + +* Call sites also extend this set with facts from type-constraint dictionaries, + case scrutinees, etc. with the exported functions 'addTyCs', 'addCoreScrutTmCs' + and 'addHsScrutTmCs'. + +Wrinkles: + +(LDI1) During patterm-match checking, we need to make an auxiliary call the Hs + desugarer to get the Core of a let-binding or where-clause. We don't want to run + the coverage checker when doing so! Efficiency is one concern, but also a lack of + properly set up long-distance information might trigger warnings that we normally + wouldn't emit. + + So `dsl_nablas :: LdiNablas` where + data LdiNablas = NoPmc | Ldi Nablas + + If dsl_nablas = NoPmc, that means we are in one of these auxiliary calls; so + we want to do no pattern-match checking whatsoever. We won't need to carry + any long-distance info around; we are simply degsugaring to Core. + + If dsl_nablas = Ldi nablas, then we do want to do pattern-match checking, + and the long-distance context is given by `nablas` + Note [Recovering from unsatisfiable pattern-matching constraints] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ===================================== compiler/GHC/HsToCore/Types.hs ===================================== @@ -7,7 +7,7 @@ -- | Various types used during desugaring. module GHC.HsToCore.Types ( - DsM, DsLclEnv(..), DsGblEnv(..), + DsM, DsLclEnv(..), DsGblEnv(..), LdiNablas(..), DsMetaEnv, DsMetaVal(..), CompleteMatches ) where @@ -85,13 +85,23 @@ data DsGblEnv instance ContainsModule DsGblEnv where extractModule = ds_mod +data LdiNablas + = NoPmc -- Do desugaring only, no pattern-match checking + -- See (LDI1) in Note [Long-distance information] + | Ldi Nablas -- Do pattern match checking; here are "reaching values" Nablas + +instance Outputable LdiNablas where + ppr NoPmc = text "NoPmc" + ppr (Ldi ns) = text "Ldi" <> braces (ppr ns) + -- | Local state of the desugarer, extended as we lexically descend data DsLclEnv = DsLclEnv { dsl_meta :: DsMetaEnv -- ^ Template Haskell bindings , dsl_loc :: RealSrcSpan -- ^ To put in pattern-matching error msgs - , dsl_nablas :: Nablas - -- ^ See Note [Long-distance information] in "GHC.HsToCore.Pmc". + + , dsl_nablas :: LdiNablas + -- ^ See Note [Long-distance information] in "GHC.HsToCore.Pmc", esp (LDI1) -- The set of reaching values Nablas is augmented as we walk inwards, refined -- through each pattern match in turn ===================================== compiler/GHC/Tc/Gen/Bind.hs ===================================== @@ -1874,9 +1874,9 @@ isClosedBndrGroup type_env binds | otherwise = True -- The free-var set for a top level binding mentions - -- * imported things so that we can report unused imports - -- * class method etc from the current module - -- * the Ids from the current Rec group + -- - imported things so that we can report unused imports + -- - class method etc from the current module + -- - the Ids from the current Rec group -- None of these will be in the type envt lHsBindFreeVars :: LHsBind GhcRn -> NameSet ===================================== compiler/GHC/Tc/Utils/Env.hs ===================================== @@ -117,7 +117,7 @@ import GHC.Utils.Misc ( HasDebugCallStack ) import GHC.Data.FastString import GHC.Data.List.SetOps -import GHC.Data.Maybe( MaybeErr(..), maybeToList, fromMaybe, isNothing ) +import GHC.Data.Maybe( MaybeErr(..), maybeToList, fromMaybe ) import GHC.Types.SrcLoc import GHC.Types.Basic hiding( SuccessFlag(..) ) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e3b527395cbcf0247824235569edc0e1... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e3b527395cbcf0247824235569edc0e1... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Simon Peyton Jones (@simonpj)