Simon Peyton Jones pushed to branch wip/T20264 at Glasgow Haskell Compiler / GHC
Commits:
-
410f1a57
by Simon Peyton Jones at 2025-04-23T15:55:03+01:00
8 changed files:
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Types/Var.hs
Changes:
... | ... | @@ -3679,10 +3679,10 @@ lintVarOcc :: InVar -> LintM OutType |
3679 | 3679 | lintVarOcc v_occ
|
3680 | 3680 | = do { in_var_env <- getInVarEnv
|
3681 | 3681 | ; case lookupVarEnv in_var_env v_occ of
|
3682 | - Nothing | isGlobalId v_occ -> return (idType v_occ)
|
|
3683 | - | otherwise -> failWithL (text "The" <+> ppr (whatItIs v_occ)
|
|
3684 | - <+> quotes (ppr v_occ)
|
|
3685 | - <+> text "is out of scope")
|
|
3682 | + Nothing | isGlobalVar v_occ -> return (idType v_occ)
|
|
3683 | + | otherwise -> failWithL (text "The" <+> ppr (whatItIs v_occ)
|
|
3684 | + <+> quotes (ppr v_occ)
|
|
3685 | + <+> text "is out of scope")
|
|
3686 | 3686 | Just (in_bndr, out_bndr) -> do { checkBndrOccCompatibility in_bndr v_occ
|
3687 | 3687 | ; return (varType out_bndr) } }
|
3688 | 3688 |
... | ... | @@ -1137,15 +1137,18 @@ occAnalRec :: OccEnv -> TopLevelFlag |
1137 | 1137 | occAnalRec !_ lvl
|
1138 | 1138 | (AcyclicSCC (ND { nd_bndr = bndr, nd_rhs = wtuds }))
|
1139 | 1139 | (WUD body_uds binds)
|
1140 | - | isDeadOcc occ -- Check for dead code: see Note [Dead code]
|
|
1141 | - = WUD body_uds binds
|
|
1142 | - |
|
1140 | + -- Currently we don't gather occ-info for tyvars,
|
|
1141 | + -- so we never discard dead bindings -- Need to fix this
|
|
1143 | 1142 | | isTyVar bndr
|
1144 | 1143 | = let (tagged_bndr, mb_join) = tagNonRecBinder lvl occ bndr
|
1145 | 1144 | !(WUD rhs_uds' rhs') = adjustNonRecRhs mb_join wtuds
|
1146 | 1145 | !bndr' = tagged_bndr
|
1147 | 1146 | in WUD (body_uds `andUDs` rhs_uds')
|
1148 | 1147 | (NonRec bndr' rhs' : binds)
|
1148 | + |
|
1149 | + | isDeadOcc occ -- Check for dead code: see Note [Dead code]
|
|
1150 | + = WUD body_uds binds
|
|
1151 | + |
|
1149 | 1152 | | otherwise
|
1150 | 1153 | = let (bndr', mb_join) = tagNonRecBinder lvl occ bndr
|
1151 | 1154 | !(WUD rhs_uds' rhs') = adjustNonRecRhs mb_join wtuds
|
... | ... | @@ -392,7 +392,8 @@ shallowTcvFolder = TyCoFolder { tcf_view = noView -- See Note [Free vars and sy |
392 | 392 | where
|
393 | 393 | do_tcv is v = Endo do_it
|
394 | 394 | where
|
395 | - do_it acc | v `elemVarSet` is = acc
|
|
395 | + do_it acc | isGlobalVar v = acc
|
|
396 | + | v `elemVarSet` is = acc
|
|
396 | 397 | | v `elemVarSet` acc = acc
|
397 | 398 | | otherwise = acc `extendVarSet` v
|
398 | 399 | |
... | ... | @@ -448,7 +449,8 @@ deepCoVarFolder = TyCoFolder { tcf_view = noView |
448 | 449 | |
449 | 450 | do_covar is v = Endo do_it
|
450 | 451 | where
|
451 | - do_it acc | v `elemVarSet` is = acc
|
|
452 | + do_it acc | isGlobalVar v = acc
|
|
453 | + | v `elemVarSet` is = acc
|
|
452 | 454 | | v `elemVarSet` acc = acc
|
453 | 455 | | otherwise = appEndo (deep_cv_ty (varType v)) $
|
454 | 456 | acc `extendVarSet` v
|
... | ... | @@ -599,9 +601,9 @@ tyCoVarsOfTypesList tys = fvVarList $ tyCoFVsOfTypes tys |
599 | 601 | tyCoFVsOfType :: Type -> FV
|
600 | 602 | -- See Note [Free variables of types]
|
601 | 603 | tyCoFVsOfType (TyVarTy v) f bound_vars (acc_list, acc_set)
|
602 | - | not (f v) = (acc_list, acc_set)
|
|
604 | + | not (f v) = (acc_list, acc_set)
|
|
603 | 605 | | v `elemVarSet` bound_vars = (acc_list, acc_set)
|
604 | - | v `elemVarSet` acc_set = (acc_list, acc_set)
|
|
606 | + | v `elemVarSet` acc_set = (acc_list, acc_set)
|
|
605 | 607 | | otherwise = tyCoFVsOfType (tyVarKind v) f
|
606 | 608 | emptyVarSet -- See Note [Closing over free variable kinds]
|
607 | 609 | (v:acc_list, extendVarSet acc_set v)
|
... | ... | @@ -2070,7 +2070,7 @@ freeNamesIfAppArgs IA_Nil = emptyNameSet |
2070 | 2070 | freeNamesIfType :: IfaceType -> NameSet
|
2071 | 2071 | freeNamesIfType (IfaceFreeTyVar {}) = emptyNameSet
|
2072 | 2072 | freeNamesIfType (IfaceTyVar {}) = emptyNameSet
|
2073 | -freeNamesIfType (IfaceExtTyVar {}) = emptyNameSet
|
|
2073 | +freeNamesIfType (IfaceExtTyVar n) = unitNameSet n
|
|
2074 | 2074 | freeNamesIfType (IfaceAppTy s t) = freeNamesIfType s &&& freeNamesIfAppArgs t
|
2075 | 2075 | freeNamesIfType (IfaceTyConApp tc ts) = freeNamesIfTc tc &&& freeNamesIfAppArgs ts
|
2076 | 2076 | freeNamesIfType (IfaceTupleTy _ _ ts) = freeNamesIfAppArgs ts
|
... | ... | @@ -761,20 +761,20 @@ chooseExternalVars opts mod binds imp_id_rules |
761 | 761 | |
762 | 762 | search [] unfold_env occ_env = return (unfold_env, occ_env)
|
763 | 763 | |
764 | - search ((idocc,referrer) : rest) unfold_env occ_env
|
|
765 | - | idocc `elemVarEnv` unfold_env = search rest unfold_env occ_env
|
|
764 | + search ((var_occ,referrer) : rest) unfold_env occ_env
|
|
765 | + | var_occ `elemVarEnv` unfold_env = search rest unfold_env occ_env
|
|
766 | 766 | | otherwise = do
|
767 | - (occ_env', name') <- tidyTopName mod name_cache (Just referrer) occ_env idocc
|
|
767 | + (occ_env', name') <- tidyTopName mod name_cache (Just referrer) occ_env var_occ
|
|
768 | 768 | let
|
769 | 769 | (new_ids, show_unfold) = addExternal opts refined_id
|
770 | 770 | |
771 | - -- 'idocc' is an *occurrence*, but we need to see the
|
|
771 | + -- 'var_occ' is an *occurrence*, but we need to see the
|
|
772 | 772 | -- unfolding in the *definition*; so look up in binder_set
|
773 | - refined_id = case lookupVarSet binder_set idocc of
|
|
773 | + refined_id = case lookupVarSet binder_set var_occ of
|
|
774 | 774 | Just id -> id
|
775 | - Nothing -> warnPprTrace True "chooseExternalVars" (ppr idocc) idocc
|
|
775 | + Nothing -> warnPprTrace True "chooseExternalVars" (ppr var_occ) var_occ
|
|
776 | 776 | |
777 | - unfold_env' = extendVarEnv unfold_env idocc (name',show_unfold)
|
|
777 | + unfold_env' = extendVarEnv unfold_env var_occ (name',show_unfold)
|
|
778 | 778 | referrer' | isExportedId refined_id = refined_id
|
779 | 779 | | otherwise = referrer
|
780 | 780 | --
|
... | ... | @@ -808,7 +808,7 @@ addExternal opts id |
808 | 808 | = (new_needed_ids, show_unfold)
|
809 | 809 | |
810 | 810 | where
|
811 | - new_needed_ids = bndrFvsInOrder show_unfold id
|
|
811 | + new_needed_ids = idBndrFvsInOrder show_unfold id
|
|
812 | 812 | idinfo = idInfo id
|
813 | 813 | unfolding = realUnfoldingInfo idinfo
|
814 | 814 | show_unfold = show_unfolding unfolding
|
... | ... | @@ -921,9 +921,9 @@ the free variables in the order that they are encountered. |
921 | 921 | See Note [Choosing external Ids]
|
922 | 922 | -}
|
923 | 923 | |
924 | -bndrFvsInOrder :: Bool -> Id -> [Var]
|
|
925 | -bndrFvsInOrder show_unfold id
|
|
926 | --- Gather the free vars of the RULES and unfolding of a binder
|
|
924 | +idBndrFvsInOrder :: Bool -> Id -> [Var]
|
|
925 | +idBndrFvsInOrder show_unfold id
|
|
926 | +-- Gather the free vars of the type, RULES and unfolding of an Id binder
|
|
927 | 927 | -- We always get the free vars of a *stable* unfolding, but
|
928 | 928 | -- for a *vanilla* one (VanillaSrc), the flag controls what happens:
|
929 | 929 | -- True <=> get fvs of even a *vanilla* unfolding
|
... | ... | @@ -933,107 +933,18 @@ bndrFvsInOrder show_unfold id |
933 | 933 | -- For top-level bindings (call from addExternal, via bndrFvsInOrder)
|
934 | 934 | -- we say "True" if we are exposing that unfolding
|
935 | 935 | = fvVarList $
|
936 | - go_unf (realUnfoldingInfo idinfo) `unionFV`
|
|
937 | - rulesFVs RhsOnly (ruleInfoRules (ruleInfo idinfo))
|
|
936 | + tyCoFVsOfType (idType id) `unionFV`
|
|
937 | + unf_fvs `unionFV`
|
|
938 | + rules_fvs
|
|
938 | 939 | where
|
939 | 940 | idinfo = idInfo id
|
940 | 941 | |
941 | - go_unf :: Unfolding -> FV
|
|
942 | - go_unf unf | show_unfold = unfoldingFVs unf
|
|
943 | - | otherwise = emptyFV
|
|
942 | + unf_fvs :: FV
|
|
943 | + unf_fvs | show_unfold = unfoldingFVs (realUnfoldingInfo idinfo)
|
|
944 | + | otherwise = emptyFV
|
|
944 | 945 | |
945 | --- = run (dffvLetBndr show_unfold id)
|
|
946 | - |
|
947 | -{-
|
|
948 | -run :: DFFV () -> [Id]
|
|
949 | -run (DFFV m) = case m emptyVarSet (emptyVarSet, []) of
|
|
950 | - ((_,ids),_) -> ids
|
|
951 | - |
|
952 | -newtype DFFV a
|
|
953 | - = DFFV (VarSet -- Envt: non-top-level things that are in scope
|
|
954 | - -- we don't want to record these as free vars
|
|
955 | - -> (VarSet, [Var]) -- Input State: (set, list) of free vars so far
|
|
956 | - -> ((VarSet,[Var]),a)) -- Output state
|
|
957 | - deriving (Functor)
|
|
958 | - |
|
959 | -instance Applicative DFFV where
|
|
960 | - pure a = DFFV $ \_ st -> (st, a)
|
|
961 | - (<*>) = ap
|
|
962 | - |
|
963 | -instance Monad DFFV where
|
|
964 | - (DFFV m) >>= k = DFFV $ \env st ->
|
|
965 | - case m env st of
|
|
966 | - (st',a) -> case k a of
|
|
967 | - DFFV f -> f env st'
|
|
968 | - |
|
969 | -extendScope :: Var -> DFFV a -> DFFV a
|
|
970 | -extendScope v (DFFV f) = DFFV (\env st -> f (extendVarSet env v) st)
|
|
971 | - |
|
972 | -extendScopeList :: [Var] -> DFFV a -> DFFV a
|
|
973 | -extendScopeList vs (DFFV f) = DFFV (\env st -> f (extendVarSetList env vs) st)
|
|
974 | - |
|
975 | -insert :: Var -> DFFV ()
|
|
976 | -insert v = DFFV $ \ env (set, ids) ->
|
|
977 | - let keep_me = isLocalId v &&
|
|
978 | - not (v `elemVarSet` env) &&
|
|
979 | - not (v `elemVarSet` set)
|
|
980 | - in if keep_me
|
|
981 | - then ((extendVarSet set v, v:ids), ())
|
|
982 | - else ((set, ids), ())
|
|
983 | - |
|
984 | - |
|
985 | -dffvExpr :: CoreExpr -> DFFV ()
|
|
986 | -dffvExpr (Var v) = insert v
|
|
987 | -dffvExpr (App e1 e2) = dffvExpr e1 >> dffvExpr e2
|
|
988 | -dffvExpr (Lam v e) = extendScope v (dffvExpr e)
|
|
989 | -dffvExpr (Tick (Breakpoint _ _ ids _) e) = mapM_ insert ids >> dffvExpr e
|
|
990 | -dffvExpr (Tick _other e) = dffvExpr e
|
|
991 | -dffvExpr (Cast e _) = dffvExpr e
|
|
992 | -dffvExpr (Let (NonRec x r) e) = dffvBind (x,r) >> extendScope x (dffvExpr e)
|
|
993 | -dffvExpr (Let (Rec prs) e) = extendScopeList (map fst prs) $
|
|
994 | - (mapM_ dffvBind prs >> dffvExpr e)
|
|
995 | -dffvExpr (Case e b _ as) = dffvExpr e >> extendScope b (mapM_ dffvAlt as)
|
|
996 | -dffvExpr _other = return ()
|
|
997 | - |
|
998 | -dffvAlt :: CoreAlt -> DFFV ()
|
|
999 | -dffvAlt (Alt _ xs r) = extendScopeList xs (dffvExpr r)
|
|
1000 | - |
|
1001 | -dffvBind :: (Var, CoreExpr) -> DFFV ()
|
|
1002 | -dffvBind(x,r)
|
|
1003 | - | not (isId x) = dffvExpr r
|
|
1004 | - | otherwise = dffvLetBndr False x >> dffvExpr r
|
|
1005 | - -- Pass False because we are doing the RHS right here
|
|
1006 | - -- If you say True you'll get *exponential* behaviour!
|
|
1007 | - |
|
1008 | -dffvLetBndr :: Bool -> Id -> DFFV ()
|
|
1009 | --- Gather the free vars of the RULES and unfolding of a binder
|
|
1010 | --- We always get the free vars of a *stable* unfolding, but
|
|
1011 | --- for a *vanilla* one (VanillaSrc), the flag controls what happens:
|
|
1012 | --- True <=> get fvs of even a *vanilla* unfolding
|
|
1013 | --- False <=> ignore a VanillaSrc
|
|
1014 | --- For nested bindings (call from dffvBind) we always say "False" because
|
|
1015 | --- we are taking the fvs of the RHS anyway
|
|
1016 | --- For top-level bindings (call from addExternal, via bndrFvsInOrder)
|
|
1017 | --- we say "True" if we are exposing that unfolding
|
|
1018 | -dffvLetBndr vanilla_unfold id
|
|
1019 | - = do { go_unf (realUnfoldingInfo idinfo)
|
|
1020 | - ; mapM_ go_rule (ruleInfoRules (ruleInfo idinfo)) }
|
|
1021 | - where
|
|
1022 | - idinfo = idInfo id
|
|
1023 | - |
|
1024 | - go_unf (CoreUnfolding { uf_tmpl = rhs, uf_src = src })
|
|
1025 | - | isStableSource src = dffvExpr rhs
|
|
1026 | - | vanilla_unfold = dffvExpr rhs
|
|
1027 | - | otherwise = return ()
|
|
1028 | - |
|
1029 | - go_unf (DFunUnfolding { df_bndrs = bndrs, df_args = args })
|
|
1030 | - = extendScopeList bndrs $ mapM_ dffvExpr args
|
|
1031 | - go_unf _ = return ()
|
|
1032 | - |
|
1033 | - go_rule (BuiltinRule {}) = return ()
|
|
1034 | - go_rule (Rule { ru_bndrs = bndrs, ru_rhs = rhs })
|
|
1035 | - = extendScopeList bndrs (dffvExpr rhs)
|
|
1036 | --}
|
|
946 | + rules_fvs :: FV
|
|
947 | + rules_fvs = rulesFVs RhsOnly (ruleInfoRules (ruleInfo idinfo))
|
|
1037 | 948 | |
1038 | 949 | {-
|
1039 | 950 | ************************************************************************
|
... | ... | @@ -761,8 +761,8 @@ substIfaceType :: IfaceTySubst -> IfaceType -> IfaceType |
761 | 761 | substIfaceType env ty
|
762 | 762 | = go ty
|
763 | 763 | where
|
764 | - go ty@(IfaceFreeTyVar tv) = ty
|
|
765 | - go ty@(IfaceExtTyVar tv) = ty
|
|
764 | + go ty@(IfaceFreeTyVar {}) = ty
|
|
765 | + go ty@(IfaceExtTyVar {}) = ty
|
|
766 | 766 | go (IfaceTyVar tv) = substIfaceTyVar env tv
|
767 | 767 | go (IfaceAppTy t ts) = IfaceAppTy (go t) (substIfaceAppArgs env ts)
|
768 | 768 | go (IfaceFunTy af w t1 t2) = IfaceFunTy af (go w) (go t1) (go t2)
|
... | ... | @@ -1148,8 +1148,8 @@ ppr_ty ctxt_prec ty |
1148 | 1148 | | not (isIfaceRhoType ty) = ppr_sigma ShowForAllMust ctxt_prec ty
|
1149 | 1149 | ppr_ty _ (IfaceForAllTy {}) = panic "ppr_ty" -- Covered by not.isIfaceRhoType
|
1150 | 1150 | ppr_ty _ (IfaceFreeTyVar tyvar) = ppr tyvar -- This is the main reason for IfaceFreeTyVar!
|
1151 | -ppr_ty _ (IfaceTyVar tyvar) = ppr tyvar -- See Note [Free TyVars and CoVars in IfaceType]
|
|
1152 | -ppr_ty _ (IfaceExtTyVar tyvar) = ppr tyvar
|
|
1151 | +ppr_ty _ (IfaceTyVar tyvar) = text "{free}" <> ppr tyvar -- See Note [Free TyVars and CoVars in IfaceType]
|
|
1152 | +ppr_ty _ (IfaceExtTyVar tyvar) = text "{ext}" <> ppr tyvar
|
|
1153 | 1153 | ppr_ty ctxt_prec (IfaceTyConApp tc tys) = pprTyTcApp ctxt_prec tc tys
|
1154 | 1154 | ppr_ty ctxt_prec (IfaceTupleTy i p tys) = ppr_tuple ctxt_prec i p tys -- always fully saturated
|
1155 | 1155 | ppr_ty _ (IfaceLitTy n) = pprIfaceTyLit n
|
... | ... | @@ -2373,9 +2373,8 @@ putIfaceType bh (IfaceTupleTy s i tys) |
2373 | 2373 | = do { putByte bh 8; put_ bh s; put_ bh i; put_ bh tys }
|
2374 | 2374 | putIfaceType bh (IfaceLitTy n)
|
2375 | 2375 | = do { putByte bh 9; put_ bh n }
|
2376 | -putIfaceType bh (IfaceExtTyVar tv) = do
|
|
2377 | - putByte bh 10
|
|
2378 | - put_ bh tv
|
|
2376 | +putIfaceType bh (IfaceExtTyVar tv)
|
|
2377 | + = do { putByte bh 10; put_ bh tv }
|
|
2379 | 2378 | |
2380 | 2379 | -- | Deserialises an 'IfaceType' from the given 'ReadBinHandle'.
|
2381 | 2380 | --
|
... | ... | @@ -726,7 +726,7 @@ tc_iface_decl _ ignore_prags (IfaceId {ifName = name, ifType = iface_type, |
726 | 726 | |
727 | 727 | tc_iface_decl _ _ (IfaceTv {ifName = name, ifTvKind = if_kind, ifTvUnf = if_type })
|
728 | 728 | = do { kind <- tcIfaceType if_kind
|
729 | - ; unf_ty <- tcIfaceType if_type
|
|
729 | + ; unf_ty <- forkM (text "IfaceTv" <+> ppr name) $ tcIfaceType if_type
|
|
730 | 730 | ; return (ATyVar (mkTyVarWithUnfolding name kind unf_ty)) }
|
731 | 731 | |
732 | 732 | tc_iface_decl _ _ (IfaceData {ifName = tc_name,
|
... | ... | @@ -62,7 +62,7 @@ module GHC.Types.Var ( |
62 | 62 | -- ** Predicates
|
63 | 63 | isId, isTyVar, isTcTyVar,
|
64 | 64 | isCoVar, isNonCoVarId, isTyCoVar,
|
65 | - isLocalVar, isGlobalVar,
|
|
65 | + isLocalVar, isGlobalVar, isGlobalTyVar,
|
|
66 | 66 | isLocalId, isLocalId_maybe, isGlobalId, isExportedId,
|
67 | 67 | mustHaveLocalBinding,
|
68 | 68 | |
... | ... | @@ -1297,6 +1297,12 @@ isGlobalVar (Id { idScope = LocalId {} }) = False |
1297 | 1297 | isGlobalVar (TyVar { varName = n }) = isExternalName n
|
1298 | 1298 | isGlobalVar (TcTyVar {}) = False
|
1299 | 1299 | |
1300 | +isGlobalTyVar :: HasDebugCallStack => Var -> Bool
|
|
1301 | +-- A TyVar with an External Name is always from another module
|
|
1302 | +isGlobalTyVar (TyVar { varName = n }) = isExternalName n
|
|
1303 | +isGlobalTyVar (TcTyVar {}) = False
|
|
1304 | +isGlobalTyVar v = pprPanic "isGlobalTyVar" (ppr v)
|
|
1305 | + |
|
1300 | 1306 | -- | 'mustHaveLocalBinding' returns @True@ of 'Id's and 'TyVar's
|
1301 | 1307 | -- that must have a binding in this module. The converse
|
1302 | 1308 | -- is not quite right: there are some global 'Id's that must have
|