Apoorv Ingle pushed to branch wip/T27154 at Glasgow Haskell Compiler / GHC Commits: 87ad4b80 by Simon Peyton Jones at 2026-04-06T13:30:20-05:00 Refactor FunResCtxt a bit Fixes #27154 - - - - - 5 changed files: - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Gen/Head.hs - compiler/GHC/Tc/Types/ErrCtxt.hs - compiler/GHC/Tc/Utils/TcType.hs - compiler/GHC/Tc/Zonk/TcType.hs Changes: ===================================== compiler/GHC/Tc/Errors/Ppr.hs ===================================== @@ -7710,12 +7710,8 @@ pprHsCtxt = \case PatSigErrCtxt sig_ty res_ty -> vcat [ hang (text "When checking that the pattern signature:") 4 (ppr sig_ty) - , nest 2 (hang (text "fits the type of its context:") 2 pp_res_ty) ] - where - -- Zonking will have turned Infer into Check - pp_res_ty = case res_ty of - Check ty -> ppr ty - Infer ir -> text "OOPS" <+> ppr ir + , nest 2 (hang (text "fits the type of its context:") + 2 (ppr (getCheckExpType res_ty))) ] PatCtxt pat -> hang (text "In the pattern:") 2 (ppr pat) @@ -7777,7 +7773,7 @@ pprHsCtxt = \case full_herald = pprExpectedFunTyHerald herald <+> speakNOf n_vis_args_in_call (text "visible argument") -- What are "visible" arguments? See Note [Visibility and arity] in GHC.Types.Basic - FunResCtxt fun n_val_args res_fun res_env n_fun n_env + FunResCtxt fun n_val_args fun_res_ty env_ty | -- Check for too few args -- fun_tau = a -> b, res_tau = Int n_fun > n_env @@ -7801,6 +7797,18 @@ pprHsCtxt = \case -> empty -- text "Debug" <+> vcat [ppr fun, ppr n_val_args, ppr res_fun, ppr res_env, ppr n_fun, ppr n_env] where + -- See Note [Splitting nested sigma types in mismatched + -- function types] + -- env_ty is an ExpRhoTy, but with simple subsumption it + -- is not /deeply/ skolemised, so still use tcSplitNestedSigmaTys + + (_,_,fun_tau) = tcSplitNestedSigmaTys fun_res_ty + (_, _, env_tau) = tcSplitNestedSigmaTys (getCheckExpType env_ty) + (args_fun, res_fun) = tcSplitFunTys fun_tau + (args_env, res_env) = tcSplitFunTys env_tau + n_fun = length args_fun + n_env = length args_env + not_fun ty -- ty is definitely not an arrow type, -- and cannot conceivably become one = case tcSplitTyConApp_maybe ty of ===================================== compiler/GHC/Tc/Gen/Head.hs ===================================== @@ -68,7 +68,6 @@ import GHC.Builtin.Names import GHC.Driver.DynFlags import GHC.Utils.Misc import GHC.Utils.Outputable as Outputable -import GHC.Utils.Panic import GHC.Data.Maybe @@ -961,7 +960,8 @@ See Note [-fno-code mode]. * * ********************************************************************* -} -addFunResCtxt :: HsExpr GhcTc -> [HsExprArg p] +addFunResCtxt :: HasDebugCallStack + => HsExpr GhcTc -> [HsExprArg p] -> TcType -> ExpRhoType -> TcM a -> TcM a -- When we have a mis-match in the return type of a function @@ -969,33 +969,10 @@ addFunResCtxt :: HsExpr GhcTc -> [HsExprArg p] -- But not in generated code, where we don't want -- to mention internal (rebindable syntax) function names addFunResCtxt fun args fun_res_ty env_ty thing_inside - = do { env_tv <- newFlexiTyVarTy liftedTypeKind - ; dumping <- doptM Opt_D_dump_tc_trace - ; msg <- mk_msg dumping env_tv - ; addErrCtxt msg thing_inside } + = addErrCtxt (FunResCtxt fun (count isValArg args) fun_res_ty env_ty) $ + thing_inside -- NB: use a landmark error context, so that an empty context -- doesn't suppress some more useful context - where - mk_msg dumping env_tv - = do { mb_env_ty <- readExpType_maybe env_ty - -- by the time the message is rendered, the ExpType - -- will be filled in (except if we're debugging) - ; env' <- case mb_env_ty of - Just env_ty -> return env_ty - Nothing -> do { massert dumping; return env_tv } - ; let -- See Note [Splitting nested sigma types in mismatched - -- function types] - (_, _, fun_tau) = tcSplitNestedSigmaTys fun_res_ty - (_, _, env_tau) = tcSplitNestedSigmaTys env' - -- env_ty is an ExpRhoTy, but with simple subsumption it - -- is not deeply skolemised, so still use tcSplitNestedSigmaTys - (args_fun, res_fun) = tcSplitFunTys fun_tau - (args_env, res_env) = tcSplitFunTys env_tau - info = - FunResCtxt fun (count isValArg args) res_fun res_env - (length args_fun) (length args_env) - ; return info } - {- Note [Splitting nested sigma types in mismatched function types] ===================================== compiler/GHC/Tc/Types/ErrCtxt.hs ===================================== @@ -251,7 +251,10 @@ data HsCtxt -- | In the instance type signature of a class method. | MethSigCtxt !Name !TcType !TcType -- | In a pattern type signature. + | PatSigErrCtxt !TcType !ExpType + -- ExpType: see Note [ExpType in HsCtxt] + -- | In a pattern. | PatCtxt !(Pat GhcRn) -- | In a pattern synonym declaration. @@ -268,7 +271,10 @@ data HsCtxt -- | In a function call. | FunTysCtxt !ExpectedFunTyCtxt !Type !Int !Int -- | In the result of a function call. - | FunResCtxt !(HsExpr GhcTc) !Int !Type !Type !Int !Int + + | FunResCtxt !(HsExpr GhcTc) !Int !TcType !ExpType + -- ExpType: see Note [ExpType in HsCtxt] + -- | In the declaration of a type constructor. | TyConDeclCtxt !Name !(TyConFlavour TyCon) -- | In a type or data family instance (or default instance). @@ -377,3 +383,14 @@ isHsCtxtLandmark (DerivBindCtxt{}) = True isHsCtxtLandmark (FunResCtxt{}) = True isHsCtxtLandmark (VDQWarningCtxt{}) = True isHsCtxtLandmark _ = False + +{- Note [ExpType in HsCtxt] +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A couple of HsCtxt constructors have ExpTypes in them. When zonking the +Infer{} case we read the hole, which should be filled in by now, and zonk +that type. Now we want to put it back: we use (Check ty') for this, so that +clients of a zonked HsCtxt don't need to be monadic. + +Result: after zonking, these ExpTypes are always (Check ty). It woudl be nice +to guarantee this statically, but it's hard to do so. +-} ===================================== compiler/GHC/Tc/Utils/TcType.hs ===================================== @@ -28,7 +28,7 @@ module GHC.Tc.Utils.TcType ( ExpType(..), ExpKind, InferResult(..), InferInstFlag(..), InferFRRFlag(..), ExpTypeFRR, ExpSigmaType, ExpSigmaTypeFRR, ExpRhoType, ExpRhoTypeFRR, - mkCheckExpType, + mkCheckExpType, getCheckExpType, checkingExpType_maybe, checkingExpType, ExpPatType(..), mkCheckExpFunPatTy, mkInvisExpPatType, @@ -440,11 +440,12 @@ data InferInstFlag -- Specifies whether the inference should return an uninstan | IIF_ShallowRho -- Trying to infer a shallow RhoType (no foralls or => at the top) -- Top-instantiate (only, regardless of DeepSubsumption) before filling the hole - -- Typically used when inferring the type of an expression + -- Used only for view patterns; see Note [View patterns and polymorphism] | IIF_DeepRho -- Trying to infer a possibly-deep RhoType (depending on DeepSubsumption) -- If DeepSubsumption is off, same as IIF_ShallowRho -- If DeepSubsumption is on, instantiate deeply before filling the hole + -- Typically used when inferring the type of an expression type ExpSigmaType = ExpType type ExpRhoType = ExpType @@ -490,6 +491,12 @@ instance Outputable InferResult where mkCheckExpType :: TcType -> ExpType mkCheckExpType = Check +getCheckExpType :: HasDebugCallStack => ExpType -> TcType +-- Expect a (Check ty). +-- See Note [ExpType in HsCtxt] in GHC.Tc.Types.ErrCtxt +getCheckExpType (Check ty) = ty +getCheckExpType (Infer ir) = pprPanic "getCheckExpType" (ppr ir) + -- | Returns the expected type when in checking mode. checkingExpType_maybe :: ExpType -> Maybe TcType checkingExpType_maybe (Check ty) = Just ty ===================================== compiler/GHC/Tc/Zonk/TcType.hs ===================================== @@ -818,19 +818,26 @@ zonkTidyHsCtxt env e@(FunAppCtxt{}) = return (env, e) zonkTidyHsCtxt env (FunTysCtxt ctxt ty i1 i2) = do (env', ty') <- zonkTidyTcType env ty return $ (env', FunTysCtxt ctxt ty' i1 i2) -zonkTidyHsCtxt env (FunResCtxt e i1 ty1 ty2 i2 i3) = do - (env', ty1') <- zonkTidyTcType env ty1 - (env', ty2') <- zonkTidyTcType env' ty2 - return $ (env', FunResCtxt e i1 ty1' ty2' i2 i3) +zonkTidyHsCtxt env (FunResCtxt e n ty1 env_ty) = do + (env', ty1') <- zonkTidyTcType env ty1 + (env', env_ty') <- zonkExpType env' env_ty + return $ (env', FunResCtxt e n ty1' env_ty') zonkTidyHsCtxt env (PatSigErrCtxt sig_ty res_ty) = do (env', sig_ty') <- zonkTidyTcType env sig_ty - (env', res_ty') <- - case res_ty of - Check ty -> zonkTidyTcType env' ty - Infer (IR {ir_ref = ref}) -> do -- inlining readExpTyp_maybe to avoid module dep loops - mb_ty <- liftIO $ readIORef ref - case mb_ty of - Nothing -> error "zonkTidyHsCtxt PatSigErrCtxt" - Just ty -> zonkTidyTcType env' ty - return (env', PatSigErrCtxt sig_ty' (Check res_ty')) + (env', res_ty') <- zonkExpType env' res_ty + return (env', PatSigErrCtxt sig_ty' res_ty') zonkTidyHsCtxt env p = return (env, p) + +zonkExpType :: TidyEnv -> ExpType -> ZonkM (TidyEnv, ExpType) +-- Zonk Infer{} to Check. The hole should have been filled in by now +zonkExpType env (Check ty) + = do { (env', ty') <- zonkTidyTcType env ty + ; return (env', Check ty') } +zonkExpType env (Infer ir@(IR { ir_ref = ref })) + = do { -- inlining readExpTyp_maybe to avoid module dep loops + ; mb_ty <- liftIO $ readIORef ref + ; case mb_ty of + Nothing -> pprPanic "zonkTidyHsCtxt PatSigErrCtxt" (ppr ir) + Just ty -> do { (env', ty') <- zonkTidyTcType env ty + ; return (env', Check ty') } } + View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/87ad4b808ae197c57094e9534e90b1d1... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/87ad4b808ae197c57094e9534e90b1d1... You're receiving this email because of your account on gitlab.haskell.org.