[Git][ghc/ghc][wip/T25266] Improve the generalisation code in Solver.simplifyInfer

Simon Peyton Jones (@simonpj) gitlab at gitlab.haskell.org
Thu Oct 17 21:53:44 UTC 2024



Simon Peyton Jones pushed to branch wip/T25266 at Glasgow Haskell Compiler / GHC


Commits:
3fb9764f by Simon Peyton Jones at 2024-10-17T22:53:12+01:00
Improve the generalisation code in Solver.simplifyInfer

The code in `decideQuantification` has become quite complicated.
This MR straightens it out, adds a new Note, and on the way
fixes #25266.

See especially Note [decideAndPromoteTyVars] which is is where
all the action happens in this MR.

- - - - -


23 changed files:

- compiler/GHC/Data/Bag.hs
- compiler/GHC/Tc/Deriv/Infer.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Instance/FunDeps.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- testsuite/tests/indexed-types/should_fail/ExtraTcsUntch.stderr
- testsuite/tests/partial-sigs/should_fail/T10615.stderr
- testsuite/tests/polykinds/T14172.stderr
- testsuite/tests/typecheck/should_compile/T13785.hs
- testsuite/tests/typecheck/should_compile/T13785.stderr
- + testsuite/tests/typecheck/should_compile/T25266.hs
- + testsuite/tests/typecheck/should_compile/T25266a.hs
- + testsuite/tests/typecheck/should_compile/T25266a.stderr
- + testsuite/tests/typecheck/should_compile/T25266b.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_fail/T18398.stderr


Changes:

=====================================
compiler/GHC/Data/Bag.hs
=====================================
@@ -16,7 +16,7 @@ module GHC.Data.Bag (
         mapBag, pprBag,
         elemBag, lengthBag,
         filterBag, partitionBag, partitionBagWith,
-        concatBag, catBagMaybes, foldBag,
+        concatBag, catBagMaybes, foldBag_flip,
         isEmptyBag, isSingletonBag, consBag, snocBag, anyBag, allBag,
         listToBag, nonEmptyToBag, bagToList, headMaybe, mapAccumBagL,
         concatMapBag, concatMapBagPair, mapMaybeBag, mapMaybeBagM, unzipBag,
@@ -194,24 +194,10 @@ partitionBagWith pred (TwoBags b1 b2)
 partitionBagWith pred (ListBag vs) = (listToBag sats, listToBag fails)
   where (sats, fails) = partitionWith pred (toList vs)
 
-foldBag :: (r -> r -> r) -- Replace TwoBags with this; should be associative
-        -> (a -> r)      -- Replace UnitBag with this
-        -> r             -- Replace EmptyBag with this
-        -> Bag a
-        -> r
-
-{- Standard definition
-foldBag t u e EmptyBag        = e
-foldBag t u e (UnitBag x)     = u x
-foldBag t u e (TwoBags b1 b2) = (foldBag t u e b1) `t` (foldBag t u e b2)
-foldBag t u e (ListBag xs)    = foldr (t.u) e xs
--}
-
--- More tail-recursive definition, exploiting associativity of "t"
-foldBag _ _ e EmptyBag        = e
-foldBag t u e (UnitBag x)     = u x `t` e
-foldBag t u e (TwoBags b1 b2) = foldBag t u (foldBag t u e b2) b1
-foldBag t u e (ListBag xs)    = foldr (t.u) e xs
+foldBag_flip :: (a -> b -> b) -> Bag a -> b -> b
+-- Just foldr with flipped arguments,
+-- so it can be chained more nicely
+foldBag_flip k bag z = foldr k z bag
 
 mapBag :: (a -> b) -> Bag a -> Bag b
 mapBag = fmap


=====================================
compiler/GHC/Tc/Deriv/Infer.hs
=====================================
@@ -763,9 +763,11 @@ simplifyDeriv (DS { ds_loc = loc, ds_tvs = tvs
        -- See [STEP DAC HOIST]
        -- From the simplified constraints extract a subset 'good' that will
        -- become the context 'min_theta' for the derived instance.
-       ; let residual_simple = approximateWC True solved_wanteds
-             head_size       = pSizeClassPred clas inst_tys
-             good = mapMaybeBag get_good residual_simple
+       ; let residual_simple = approximateWC False solved_wanteds
+                -- False: ignore any non-quantifiable constraints,
+                --        including equalities hidden under Given equalities
+             head_size = pSizeClassPred clas inst_tys
+             good      = mapMaybeBag get_good residual_simple
 
              -- Returns @Just p@ (where @p@ is the type of the Ct) if a Ct is
              -- suitable to be inferred in the context of a derived instance.


=====================================
compiler/GHC/Tc/Gen/Bind.hs
=====================================
@@ -490,8 +490,8 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc closed bind_list
     ; let plan = decideGeneralisationPlan dflags top_lvl closed sig_fn bind_list
     ; traceTc "Generalisation plan" (ppr plan)
     ; result@(_, scaled_poly_ids) <- case plan of
-         NoGen              -> tcPolyNoGen rec_tc prag_fn sig_fn bind_list
-         InferGen           -> tcPolyInfer rec_tc prag_fn sig_fn bind_list
+         NoGen              -> tcPolyNoGen         rec_tc prag_fn sig_fn bind_list
+         InferGen           -> tcPolyInfer top_lvl rec_tc prag_fn sig_fn bind_list
          CheckGen lbind sig -> tcPolyCheck prag_fn sig lbind
 
     ; let poly_ids = map scaledThing scaled_poly_ids
@@ -708,12 +708,13 @@ To address this we to do a few things
 -}
 
 tcPolyInfer
-  :: RecFlag       -- Whether it's recursive after breaking
+  :: TopLevelFlag
+  -> RecFlag       -- Whether it's recursive after breaking
                    -- dependencies based on type signatures
   -> TcPragEnv -> TcSigFun
   -> [LHsBind GhcRn]
   -> TcM (LHsBinds GhcTc, [Scaled TcId])
-tcPolyInfer rec_tc prag_fn tc_sig_fn bind_list
+tcPolyInfer top_lvl rec_tc prag_fn tc_sig_fn bind_list
   = do { (tclvl, wanted, (binds', mono_infos))
              <- pushLevelAndCaptureConstraints  $
                 tcMonoBinds rec_tc tc_sig_fn LetLclBndr bind_list
@@ -733,7 +734,7 @@ tcPolyInfer rec_tc prag_fn tc_sig_fn bind_list
 
        ; traceTc "simplifyInfer call" (ppr tclvl $$ ppr name_taus $$ ppr wanted)
        ; ((qtvs, givens, ev_binds, insoluble), residual)
-            <- captureConstraints $ simplifyInfer tclvl infer_mode sigs name_taus wanted
+            <- captureConstraints $ simplifyInfer top_lvl tclvl infer_mode sigs name_taus wanted
 
        ; let inferred_theta = map evVarPred givens
        ; scaled_exports <- checkNoErrs $


=====================================
compiler/GHC/Tc/Gen/Head.hs
=====================================
@@ -696,7 +696,8 @@ tcExprSig expr sig@(TcPartialSig (PSig { psig_name = name, psig_loc = loc }))
                         | otherwise
                         = NoRestrictions
        ; ((qtvs, givens, ev_binds, _), residual)
-           <- captureConstraints $ simplifyInfer tclvl infer_mode [sig_inst] [(name, tau)] wanted
+           <- captureConstraints $
+              simplifyInfer NotTopLevel tclvl infer_mode [sig_inst] [(name, tau)] wanted
        ; emitConstraints residual
 
        ; tau <- liftZonkM $ zonkTcType tau


=====================================
compiler/GHC/Tc/Instance/FunDeps.hs
=====================================
@@ -578,11 +578,22 @@ closeWrtFunDeps preds fixed_tvs
        = case classifyPredType pred of
             EqPred NomEq t1 t2 -> [([t1],[t2]), ([t2],[t1])]
                -- See Note [Equality superclasses]
-            ClassPred cls tys  -> [ instFD fd cls_tvs tys
-                                  | let (cls_tvs, cls_fds) = classTvsFds cls
-                                  , fd <- cls_fds ]
+
+            ClassPred cls tys | not (isIPClass cls)
+               -- isIPClass: see Note [closeWrtFunDeps ignores implicit parameters]
+                              -> [ instFD fd cls_tvs tys
+                                 | let (cls_tvs, cls_fds) = classTvsFds cls
+                                 , fd <- cls_fds ]
             _ -> []
 
+{- Note [closeWrtFunDeps ignores implicit parameters]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Implicit params don't really determine a type variable (that is, we might have
+IP "c" Bool and IP "c" Int in different places within the same program), and
+skipping this causes implicit params to monomorphise too many variables; see
+Note [Inheriting implicit parameters] in GHC.Tc.Solver.  Skipping causes
+typecheck/should_compile/tc219 to fail.
+-}
 
 {- *********************************************************************
 *                                                                      *


=====================================
compiler/GHC/Tc/Module.hs
=====================================
@@ -2582,7 +2582,7 @@ tcRnExpr hsc_env mode rdr_expr
     let { fresh_it = itName uniq (getLocA rdr_expr) } ;
     ((qtvs, dicts, _, _), residual)
          <- captureConstraints $
-            simplifyInfer tclvl infer_mode
+            simplifyInfer TopLevel tclvl infer_mode
                           []    {- No sig vars -}
                           [(fresh_it, res_ty)]
                           lie ;


=====================================
compiler/GHC/Tc/Solver.hs
=====================================
@@ -14,6 +14,7 @@ module GHC.Tc.Solver(
        tcCheckGivens,
        tcCheckWanteds,
        tcNormalise,
+       approximateWC,    -- Exported for plugins to use
 
        captureTopConstraints,
 
@@ -48,7 +49,7 @@ import GHC.Tc.Utils.TcType
 import GHC.Core.Predicate
 import GHC.Core.Type
 import GHC.Core.Ppr
-import GHC.Core.TyCon    ( TyConBinder, isTypeFamilyTyCon )
+import GHC.Core.TyCon    ( TyConBinder )
 
 import GHC.Types.Name
 import GHC.Types.Id
@@ -58,9 +59,11 @@ import GHC.Types.Var.Set
 import GHC.Types.Basic
 import GHC.Types.Error
 
-import GHC.Utils.Misc
+import GHC.Driver.DynFlags( DynFlags, xopt )
+import GHC.Driver.Flags( WarningFlag(..) )
 import GHC.Utils.Panic
 import GHC.Utils.Outputable
+import GHC.Utils.Misc( filterOut )
 
 import GHC.Data.Bag
 
@@ -882,7 +885,8 @@ instance Outputable InferMode where
   ppr EagerDefaulting = text "EagerDefaulting"
   ppr NoRestrictions  = text "NoRestrictions"
 
-simplifyInfer :: TcLevel               -- Used when generating the constraints
+simplifyInfer :: TopLevelFlag
+              -> TcLevel               -- Used when generating the constraints
               -> InferMode
               -> [TcIdSigInst]         -- Any signatures (possibly partial)
               -> [(Name, TcTauType)]   -- Variables to be generalised,
@@ -893,7 +897,7 @@ simplifyInfer :: TcLevel               -- Used when generating the constraints
                       TcEvBinds,    -- ... binding these evidence variables
                       Bool)         -- True <=> the residual constraints are insoluble
 
-simplifyInfer rhs_tclvl infer_mode sigs name_taus wanteds
+simplifyInfer top_lvl rhs_tclvl infer_mode sigs name_taus wanteds
   | isEmptyWC wanteds
    = do { -- When quantifying, we want to preserve any order of variables as they
           -- appear in partial signatures. cf. decideQuantifiedTyVars
@@ -946,9 +950,8 @@ simplifyInfer rhs_tclvl infer_mode sigs name_taus wanteds
        ; wanted_transformed <- TcM.liftZonkM $ TcM.zonkWC wanted_transformed
        ; let definite_error = insolubleWC wanted_transformed
                               -- See Note [Quantification with errors]
-             quant_pred_candidates
-               | definite_error = []
-               | otherwise      = ctsPreds (approximateWC False wanted_transformed)
+             wanted_dq | definite_error = emptyWC
+                       | otherwise      = wanted_transformed
 
        -- Decide what type variables and constraints to quantify
        -- NB: quant_pred_candidates is already fully zonked
@@ -957,9 +960,11 @@ simplifyInfer rhs_tclvl infer_mode sigs name_taus wanteds
        -- NB: bound_theta are fully zonked
        -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
        --           in GHC.Tc.Utils.TcType
-       ; rec { (qtvs, bound_theta, co_vars) <- decideQuantification skol_info infer_mode rhs_tclvl
-                                                     name_taus partial_sigs
-                                                     quant_pred_candidates
+       ; rec { (qtvs, bound_theta, co_vars) <- decideQuantification
+                                                     top_lvl rhs_tclvl infer_mode
+                                                     skol_info name_taus partial_sigs
+                                                     wanted_dq
+
              ; bound_theta_vars <- mapM TcM.newEvVar bound_theta
 
              ; let full_theta = map idType bound_theta_vars
@@ -975,7 +980,7 @@ simplifyInfer rhs_tclvl infer_mode sigs name_taus wanteds
 
          -- All done!
        ; traceTc "} simplifyInfer/produced residual implication for quantification" $
-         vcat [ text "quant_pred_candidates =" <+> ppr quant_pred_candidates
+         vcat [ text "wanted_dq ="      <+> ppr wanted_dq
               , text "psig_theta ="     <+> ppr psig_theta
               , text "bound_theta ="    <+> pprCoreBinders bound_theta_vars
               , text "qtvs ="           <+> ppr qtvs
@@ -1278,20 +1283,21 @@ simplifyInfer.
 -}
 
 decideQuantification
-  :: SkolemInfo
-  -> InferMode
+  :: TopLevelFlag
   -> TcLevel
+  -> InferMode
+  -> SkolemInfo
   -> [(Name, TcTauType)]   -- Variables to be generalised
   -> [TcIdSigInst]         -- Partial type signatures (if any)
-  -> [PredType]            -- Candidate theta; already zonked
+  -> WantedConstraints     -- Candidate theta; already zonked
   -> TcM ( [TcTyVar]       -- Quantify over these (skolems)
          , [PredType]      -- and this context (fully zonked)
          , CoVarSet)
 -- See Note [Deciding quantification]
-decideQuantification skol_info infer_mode rhs_tclvl name_taus psigs candidates
+decideQuantification top_lvl rhs_tclvl infer_mode skol_info name_taus psigs wanted
   = do { -- Step 1: find the mono_tvs
-       ; (candidates, co_vars, mono_tvs0)
-             <- decidePromotedTyVars infer_mode name_taus psigs candidates
+       ; (candidates, co_vars)
+             <- decideAndPromoteTyVars top_lvl rhs_tclvl infer_mode name_taus psigs wanted
 
        -- Step 2: default any non-mono tyvars, and re-simplify
        -- This step may do some unification, but result candidates is zonked
@@ -1308,11 +1314,11 @@ decideQuantification skol_info infer_mode rhs_tclvl name_taus psigs candidates
           do { candidates <- TcM.zonkTcTypes candidates
              ; psig_theta <- TcM.zonkTcTypes (concatMap sig_inst_theta psigs)
              ; return (candidates, psig_theta) }
-       ; min_theta  <- pickQuantifiablePreds (mkVarSet qtvs) mono_tvs0 candidates
 
        -- Take account of partial type signatures
        -- See Note [Constraints in partial type signatures]
        ; let min_psig_theta = mkMinimalBySCs id psig_theta
+             min_theta      = pickQuantifiablePreds (mkVarSet qtvs) candidates
        ; theta <- if
            | null psigs -> return min_theta                 -- Case (P3)
            | not (all has_extra_constraints_wildcard psigs) -- Case (P2)
@@ -1396,147 +1402,376 @@ Some rationale and observations
     g :: forall b. Show b => F b -> _ -> b
     g x y = let _ = (f y, show x) in x
   But that's a battle for another day.
+
+Note [Generalising top-level bindings]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider
+  class C a b | a -> b where ..
+  f x = ...[W] C Int beta[1]...
+
+When generalising `f`, closeWrtFunDeps will promote beta[1] to beta[0].
+But we do NOT want to make a top level type
+  f :: C Int beta[0] => blah
+The danger is that beta[0] is defaulted to Any, and that then appears
+in a user error message.  Even if the type `blah` mentions beta[0], /and/
+there is a call that fixes beta[0] to (say) Bool, we'll end up with
+[W] C Int Bool, which is insoluble.  Why insoluble? If there was an
+   instance C Int Bool
+then fundeps would have fixed beta:=Bool in the first place.
+
+If the binding of `f` is nested, things are different: we can
+definitely see all the calls.
+
+For nested bindings, I think it just doesn't matter. No one cares what this
+variable ends up being; it seems silly to halt compilation around it. (Like in
+the length [] case.)
 -}
 
-decidePromotedTyVars :: InferMode
-                     -> [(Name,TcType)]
-                     -> [TcIdSigInst]
-                     -> [PredType]
-                     -> TcM ([PredType], CoVarSet, TcTyVarSet)
--- We are about to generalise over type variables at level N
--- Each must be either
---    (P) promoted
---    (D) defaulted
---    (Q) quantified
--- This function finds (P), the type variables that we are going to promote:
---   (a) Mentioned in a constraint we can't generalise (the MR)
---   (b) Mentioned in the kind of a CoVar; we can't quantify over a CoVar,
---       so we must not quantify over a type variable free in its kind
---   (c) Connected by an equality or fundep to
---          * a type variable at level < N, or
---          * A tyvar subject to (a), (b) or (c)
--- Having found all such level-N tyvars that we can't generalise,
--- promote them, to eliminate them from further consideration.
---
--- Also return CoVars that appear free in the final quantified types
---   we can't quantify over these, and we must make sure they are in scope
-decidePromotedTyVars infer_mode name_taus psigs candidates
-  = do { tc_lvl <- TcM.getTcLevel
-       ; (no_quant, maybe_quant) <- pick infer_mode candidates
+decideAndPromoteTyVars :: TopLevelFlag -> TcLevel
+                       -> InferMode
+                       -> [(Name,TcType)]
+                       -> [TcIdSigInst]
+                       -> WantedConstraints
+                       -> TcM ([PredType], CoVarSet)
+-- See Note [decideAndPromoteTyVars]
+decideAndPromoteTyVars top_lvl rhs_tclvl infer_mode name_taus psigs wanted
+  = do { dflags <- getDynFlags
 
        -- If possible, we quantify over partial-sig qtvs, so they are
        -- not mono. Need to zonk them because they are meta-tyvar TyVarTvs
-       ; (psig_qtvs, psig_theta, taus) <- TcM.liftZonkM $
-          do { psig_qtvs <- zonkTcTyVarsToTcTyVars $ binderVars $
-                            concatMap (map snd . sig_inst_skols) psigs
-             ; psig_theta <- mapM TcM.zonkTcType $
-                             concatMap sig_inst_theta psigs
-             ; taus <- mapM (TcM.zonkTcType . snd) name_taus
-             ; return (psig_qtvs, psig_theta, taus) }
+       ; (psig_qtvs, psig_theta, tau_tys) <- getSeedTys name_taus psigs
 
-       ; let psig_tys = mkTyVarTys psig_qtvs ++ psig_theta
+       ; let is_top_level = isTopLevel top_lvl  -- A syntactically top-level binding
 
-             -- (b) The co_var_tvs are tvs mentioned in the types of covars or
+             -- Step 1 of Note [decideAndPromoteTyVars]
+             -- Get candidate constraints, decide which we can potentially quantify
+             (can_quant_cts, no_quant_cts) = approximateWCX wanted
+             can_quant = ctsPreds can_quant_cts
+             no_quant  = ctsPreds no_quant_cts
+
+             -- Step 2 of Note [decideAndPromoteTyVars]
+             -- Apply the monomorphism restriction
+             (post_mr_quant, mr_no_quant) = applyMR dflags infer_mode can_quant
+
+             -- The co_var_tvs are tvs mentioned in the types of covars or
              -- coercion holes. We can't quantify over these covars, so we
              -- must include the variable in their types in the mono_tvs.
              -- E.g.  If we can't quantify over co :: k~Type, then we can't
              --       quantify over k either!  Hence closeOverKinds
              -- Recall that coVarsOfTypes also returns coercion holes
-             co_vars = coVarsOfTypes (psig_tys ++ taus ++ candidates)
+             co_vars    = coVarsOfTypes (mkTyVarTys psig_qtvs ++ psig_theta
+                                         ++ tau_tys ++ post_mr_quant)
              co_var_tvs = closeOverKinds co_vars
 
-             mono_tvs0 = filterVarSet (not . isQuantifiableTv tc_lvl) $
-                         tyCoVarsOfTypes candidates
-               -- We need to grab all the non-quantifiable tyvars in the
-               -- types so that we can grow this set to find other
-               -- non-quantifiable tyvars. This can happen with something like
-               --    f x y = ...
-               --      where z = x 3
-               -- The body of z tries to unify the type of x (call it alpha[1])
-               -- with (beta[2] -> gamma[2]). This unification fails because
-               -- alpha is untouchable, leaving [W] alpha[1] ~ (beta[2] -> gamma[2]).
-               -- We need to know not to quantify over beta or gamma, because they
-               -- are in the equality constraint with alpha. Actual test case:
-               -- typecheck/should_compile/tc213
-
-             mono_tvs1 = mono_tvs0 `unionVarSet` co_var_tvs
-
-               -- mono_tvs1 is now the set of variables from an outer scope
-               -- (that's mono_tvs0) and the set of covars, closed over kinds.
-               -- Given this set of variables we know we will not quantify,
-               -- we want to find any other variables that are determined by this
-               -- set, by functional dependencies or equalities. We thus use
-               -- closeWrtFunDeps to find all further variables determined by this root
-               -- set. See Note [growThetaTyVars vs closeWrtFunDeps]
-
-             non_ip_candidates = filterOut isIPLikePred candidates
-               -- implicit params don't really determine a type variable
-               -- (that is, we might have IP "c" Bool and IP "c" Int in different
-               -- places within the same program), and
-               -- skipping this causes implicit params to monomorphise too many
-               -- variables; see Note [Inheriting implicit parameters] in GHC.Tc.Solver.
-               -- Skipping causes typecheck/should_compile/tc219 to fail.
-
-             mono_tvs2 = closeWrtFunDeps non_ip_candidates mono_tvs1
-               -- mono_tvs2 now contains any variable determined by the "root
-               -- set" of monomorphic tyvars in mono_tvs1.
-
-             constrained_tvs = filterVarSet (isQuantifiableTv tc_lvl) $
-                               closeWrtFunDeps non_ip_candidates (tyCoVarsOfTypes no_quant)
-                                `minusVarSet` mono_tvs2
-             -- constrained_tvs: the tyvars that we are not going to
-             -- quantify /solely/ because of the monomorphism restriction
-             --
-             -- (`minusVarSet` mono_tvs2): a type variable is only
-             --   "constrained" (so that the MR bites) if it is not
-             --   free in the environment (#13785) or is determined
-             --   by some variable that is free in the env't
-
-             mono_tvs = (mono_tvs2 `unionVarSet` constrained_tvs)
-                        `delVarSetList` psig_qtvs
-             -- (`delVarSetList` psig_qtvs): if the user has explicitly
-             --   asked for quantification, then that request "wins"
-             --   over the MR.
-             --
-             -- What if a psig variable is also free in the environment
-             -- (i.e. says "no" to isQuantifiableTv)? That's OK: explanation
-             -- in Step 2 of Note [Deciding quantification].
-
-           -- Warn about the monomorphism restriction
-       ; when (case infer_mode of { ApplyMR -> True; _ -> False}) $ do
-           let dia = TcRnMonomorphicBindings (map fst name_taus)
-           diagnosticTc (constrained_tvs `intersectsVarSet` tyCoVarsOfTypes taus) dia
-
-       -- Promote the mono_tvs: see Note [Promote monomorphic tyvars]
-       ; _ <- promoteTyVarSet mono_tvs
-
-       ; traceTc "decidePromotedTyVars" $ vcat
-           [ text "infer_mode =" <+> ppr infer_mode
+             -- outer_tvs are mentioned in `wanted, and belong to some outer level.
+             -- We definitely can't quantify over them
+             outer_tvs = outerLevelTyVars rhs_tclvl $
+                         tyCoVarsOfTypes can_quant `unionVarSet` tyCoVarsOfTypes no_quant
+
+             -- Step 3 of Note [decideAndPromoteTyVars]
+             -- Identify mono_tvs: the type variables that we must not quantify over
+             mono_tvs_without_mr
+               | is_top_level = outer_tvs
+               | otherwise    = outer_tvs                                 -- (a)
+                                `unionVarSet` tyCoVarsOfTypes no_quant    -- (b)
+                                `unionVarSet` co_var_tvs                  -- (c)
+
+             mono_tvs_with_mr
+               = -- Even at top level, we don't quantify over type variables
+                 -- mentioned in constraints that the MR tells us not to quantify
+                 -- See Note [decideAndPromoteTyVars] (DP2)
+                 mono_tvs_without_mr `unionVarSet` tyCoVarsOfTypes mr_no_quant
+
+             --------------------------------------------------------------------
+             -- Step 4 of Note [decideAndPromoteTyVars]
+             -- Use closeWrtFunDeps to find any other variables that are determined by mono_tvs
+             add_determined tvs = closeWrtFunDeps post_mr_quant tvs
+                                  `delVarSetList` psig_qtvs
+                 -- Why delVarSetList psig_qtvs?
+                 -- If the user has explicitly asked for quantification, then that
+                 -- request "wins" over the MR.
+                 --
+                 -- What if a psig variable is also free in the environment
+                 -- (i.e. says "no" to isQuantifiableTv)? That's OK: explanation
+                 -- in Step 2 of Note [Deciding quantification].
+
+             mono_tvs_with_mr_det    = add_determined mono_tvs_with_mr
+             mono_tvs_without_mr_det = add_determined mono_tvs_without_mr
+
+             --------------------------------------------------------------------
+             -- Step 5 of Note [decideAndPromoteTyVars]
+             -- Do not quantify over any constraint mentioning a "newly-mono" tyvar.
+             newly_mono_tvs = mono_tvs_with_mr_det `minusVarSet` mono_tvs_with_mr
+             final_quant
+               | is_top_level = filterOut (predMentions newly_mono_tvs) post_mr_quant
+               | otherwise    = post_mr_quant
+
+       --------------------------------------------------------------------
+       -- Check if the Monomorphism Restriction has bitten
+       ; warn_mr <- woptM Opt_WarnMonomorphism
+       ; when (warn_mr && case infer_mode of { ApplyMR -> True; _ -> False}) $
+         diagnosticTc (not (mono_tvs_with_mr_det `subVarSet` mono_tvs_without_mr_det)) $
+              TcRnMonomorphicBindings (map fst name_taus)
+             -- If there is a variable in mono_tvs, but not in mono_tvs_wo_mr
+             -- then the MR has "bitten" and reduced polymorphism.
+
+       --------------------------------------------------------------------
+       -- Step 6: Promote the mono_tvs: see Note [Promote monomorphic tyvars]
+       ; _ <- promoteTyVarSet mono_tvs_with_mr_det
+
+       ; traceTc "decideAndPromoteTyVars" $ vcat
+           [ text "rhs_tclvl =" <+> ppr rhs_tclvl
+           , text "top =" <+> ppr is_top_level
+           , text "infer_mode =" <+> ppr infer_mode
            , text "psigs =" <+> ppr psigs
            , text "psig_qtvs =" <+> ppr psig_qtvs
-           , text "mono_tvs0 =" <+> ppr mono_tvs0
+           , text "outer_tvs =" <+> ppr outer_tvs
+           , text "mono_tvs_with_mr =" <+> ppr mono_tvs_with_mr
+           , text "mono_tvs_without_mr =" <+> ppr mono_tvs_without_mr
+           , text "mono_tvs_with_mr_det =" <+> ppr mono_tvs_with_mr_det
+           , text "mono_tvs_without_mr_det =" <+> ppr mono_tvs_without_mr_det
+           , text "newly_mono_tvs =" <+> ppr newly_mono_tvs
+           , text "can_quant =" <+> ppr can_quant
+           , text "post_mr_quant =" <+> ppr post_mr_quant
            , text "no_quant =" <+> ppr no_quant
-           , text "maybe_quant =" <+> ppr maybe_quant
-           , text "mono_tvs =" <+> ppr mono_tvs
+           , text "mr_no_quant =" <+> ppr mr_no_quant
+           , text "final_quant =" <+> ppr final_quant
            , text "co_vars =" <+> ppr co_vars ]
 
-       ; return (maybe_quant, co_vars, mono_tvs0) }
+       ; return (final_quant, co_vars) }
+          -- We return `co_vars` that appear free in the final quantified types
+          -- we can't quantify over these, and we must make sure they are in scope
+
+-------------------
+applyMR :: DynFlags -> InferMode -> [PredType]
+        -> ( [PredType]   -- Quantify over these
+           , [PredType] ) -- But not over these
+-- Split the candidates into ones we definitely
+-- won't quantify, and ones that we might
+applyMR _      NoRestrictions  cand = (cand, [])
+applyMR _      ApplyMR         cand = ([], cand)
+applyMR dflags EagerDefaulting cand = partition not_int_ct cand
   where
-    pick :: InferMode -> [PredType] -> TcM ([PredType], [PredType])
-    -- Split the candidates into ones we definitely
-    -- won't quantify, and ones that we might
-    pick ApplyMR         cand = return (cand, [])
-    pick NoRestrictions  cand = return ([], cand)
-    pick EagerDefaulting cand = do { os <- xoptM LangExt.OverloadedStrings
-                                   ; return (partition (is_int_ct os) cand) }
-
-    -- is_int_ct returns True for a constraint we should /not/ quantify
+    ovl_strings = xopt LangExt.OverloadedStrings dflags
+
+    -- not_int_ct returns True for a constraint we /can/ quantify
     -- For EagerDefaulting, do not quantify over
     -- over any interactive class constraint
-    is_int_ct ovl_strings pred
+    not_int_ct pred
       = case classifyPredType pred of
-           ClassPred cls _ -> isInteractiveClass ovl_strings cls
-           _               -> False
+           ClassPred cls _ -> not (isInteractiveClass ovl_strings cls)
+           _               -> True
+
+-------------------
+outerLevelTyVars :: TcLevel -> TcTyVarSet -> TcTyVarSet
+-- Find just the tyvars that are bound outside rhs_tc_lvl
+outerLevelTyVars rhs_tclvl tvs
+  = filterVarSet is_outer_tv tvs
+  where
+    is_outer_tv tcv
+     | isTcTyVar tcv  -- Might be a CoVar; change this when gather covars separately
+     = rhs_tclvl `strictlyDeeperThan` tcTyVarLevel tcv
+     | otherwise
+     = False
+
+{- Note [decideAndPromoteTyVars]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We are about to generalise a let-binding at "outer level" N, where we have
+typechecked its RHS at "rhs level" N+1.  Each tyvar must be either
+  (P) promoted
+  (D) defaulted
+  (Q) quantified
+The function `decideAndPromoteTyVars` figures out (P), the type variables
+mentioned in constraints should definitely not be quantified, and promotes them
+to the outer level, namely (N-1).
+
+The plan
+
+* Step 1.  Use `approximateWCX` to extract, from the RHS `WantedConstraints`,
+  the PredTypes that we might quantify over; and also those that we can't.
+  Example: suppose the `wanted` is this:
+     (d1:Eq alpha, forall b. (F b ~ a) => (co:t1 ~ t2), (d:Show alpha))
+  Then
+     can_quant = [Eq alpha, Show alpha]
+     no_quant  = (t1 ~ t2)
+  We can't quantify over that (t1~t2) because of the enclosing equality (F b ~ a).
+
+  We also choose never to quantify over some forms of equality constraints.
+  Both this and the "given-equality" thing are described in
+  Note [Quantifying over equality constraints] in GHC.Tc.Types.Constraint.
+
+* Step 2. Further trim can_quant using the Monomorphism Restriction, yielding the
+  further `mr_no_quant` predicates that we won't quantify over; plus `post_mr_quant`,
+  which we can in principle quantify.
+
+* Step 3. Identify the type variables we definitely won't quantify, because they are:
+  a) From an outer level <=N anyway
+  b) Mentioned in a constraint we /can't/ quantify.  See Wrinkle (DP1).
+  c) Mentioned in the kind of a CoVar; we can't quantify over a CoVar,
+     so we must not quantify over a type variable free in its kind
+  d) Mentioned in a constraint that the MR says we should not quantify.
+
+  There is a special case for top-level bindings: see Wrinkle (DP2).
+
+* Step 4.  Close wrt functional dependencies and equalities.Example
+  Example
+           f x y = ...
+              where z = x 3
+  The body of z tries to unify the type of x (call it alpha[1]) with
+  (beta[2] -> gamma[2]). This unification fails because alpha is untouchable, leaving
+       [W] alpha[1] ~ (beta[2] -> gamma[2])
+  We need to know not to quantify over beta or gamma, because they are in the
+  equality constraint with alpha. Actual test case:   typecheck/should_compile/tc213
+
+  Another example. Suppose we have
+      class C a b | a -> b
+  and a constraint ([W] C alpha beta), if we promote alpha we should promote beta.
+
+  See also Note [growThetaTyVars vs closeWrtFunDeps]
+
+* Step 5. Further restrict the quantifiable constraints `post_mr_quant` to ones
+  that do not mention a "newly mono" tyvar. The "newly-mono" tyvars are the ones
+  not free in the envt, nor forced to be promoted by the MR; but are determined
+  (via fundeps) by them. Example:
+           class C a b | a -> b
+           [W] C Int beta[1],  tau = beta[1]->Int
+  We promote beta[1] to beta[0] since it is determined by fundep, but we do not
+  want to generate f :: (C Int beta[0]) => beta[0] -> Int Rather, we generate
+  f :: beta[0] -> Int, but leave [W] C Int beta[0] in the residual constraints,
+  which will probably cause a type error
+
+  See Note [Do not quantify over constraints that determine a variable]
+
+* Step 6: acutally promote the type variables we don't want to quantify.
+  We must do this: see Note [Promote monomorphic tyvars].
+
+We also add a warning that signals when the MR "bites".
+
+Wrinkles
+
+(DP1) In step 3, why (b)?  Consider the example given in Step 1.  we can't
+  quantify over the constraint (t1~t2).  But if we quantify over the /tyvars/ in
+  t1 or t2, we may simply make that constraint insoluble (#25266 was an example).
+
+(DP2) In Step 3, for top-level bindings, we do (a,d), but /not/ (b,c). Reason:
+  see Note [The top-level Any principle].  At top level we are very reluctant to
+  promote type variables.  But for bindings affected by the MR we have no choice
+  but to promote.
+
+Note [The top-level Any principle]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Key principle: we never want to show the programmer a type with `Any` in it.
+
+Most /top level/ bindings have a type signature, so none of this arises.  But
+where a top-level binding lacks a signature, we don't want to infer a type like
+    f :: alpha[0] -> Int
+and then subsequently default alpha[0]:=Any.  Exposing `Any` to the user is bad
+bad bad.  Better to report an error, which is what may well happen if we
+quantify over alpha instead.
+
+For /nested/ bindings, a monomorphic type like `f :: alpha[0] -> Int` is fine,
+because we can see all the call sites of `f`, and they will probably fix
+`alpha`.  In contrast, we can't see all of (or perhaps any of) the calls of
+top-level (exported) functions, reducing the worries about "spooky action at a
+distance".
+
+Note [Do not quantify over constraints that determine a variable]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider (typecheck/should_compile/tc231), where we're trying to infer
+the type of a top-level declaration. We have
+  class Zork s a b | a -> b
+and the candidate constraint at the end of simplifyInfer is
+  [W] Zork alpha[1] (Z [Char]) beta[1]
+We definitely want to quantify over `alpha` (which is mentioned in the
+tau-type).
+
+But we do *not* want to quantify over `beta`: it is determined by the
+functional dependency on Zork: note that the second argument to Zork
+in the Wanted is a variable-free `Z [Char]`.  Quantifying over it
+would be "Henry Ford polymorphism".  (Presumably we don't have an
+instance in scope that tells us what `beta` actually is.)  Instead
+we promote `beta[1]` to `beta[0]`, in `decidePromotedTyVars`.
+
+The question here: do we want to quantify over the constraint, to
+give the type
+   forall a. Zork a (Z [Char]) beta[0] => blah
+Definitely not: see Note [The top-level Any principle]
+
+What we really want (to catch the Zork example) is this:
+
+   Quantify over the constraint only if all its free variables are
+   (a) quantified, or
+   (b) appears in the type of something in the environment (mono_tvs0).
+
+To understand (b) consider
+
+  class C a b where { op :: a -> b -> () }
+
+  mr = 3                      -- mr :: alpha
+  f1 x = op x mr              -- f1 :: forall b. b -> (), plus [W] C b alpha
+  intify = mr + (4 :: Int)
+
+In `f1` should we quantify over that `(C b alpha)`?  Answer: since `alpha` is
+free in the type envt, yes we should.  After all, if we'd typechecked `intify`
+first, we'd have set `alpha := Int`, and /then/ we'd certainly quantify.  The
+delicate Zork situation applies when beta is completely unconstrained (not free
+in the environment) -- except by the fundep.  Hence `newly_mono`.
+
+Another way to put it: let's say `alpha` is in `outer_tvs`. It must be that
+some variable `x` has `alpha` free in its type. If we are at top-level (and we
+are, because nested decls don't go through this path all), then `x` must also
+be at top-level. And, by induction, `x` will not have Any in its type when all
+is said and done. The induction is well-founded because, if `x` is mutually
+recursive with the definition at hand, then their constraints get processed
+together (or `x` has a type signature, in which case the type doesn't have
+`Any`). So the key thing is that we must not introduce a new top-level
+unconstrained variable here.
+
+However this regrettably-subtle reasoning is needed only for /top-level/
+declarations.  For /nested/ decls we can see all the calls, so we'll instantiate
+that quantifed `Zork a (Z [Char]) beta` constraint at call sites, and either
+solve it or not (probably not).  We won't be left with a still-callable function
+with Any in its type.  So for nested definitions we don't make this tricky test.
+
+Historical note: we had a different, and more complicated test before, but it
+was utterly wrong: #23199.
+
+Note [Promote monomorphic tyvars]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Promote any type variables that are free in the environment.  Eg
+   f :: forall qtvs. bound_theta => zonked_tau
+The free vars of f's type become free in the envt, and hence will show
+up whenever 'f' is called.  They may currently at rhs_tclvl, but they
+had better be unifiable at the outer_tclvl!  Example: envt mentions
+alpha[1]
+           tau_ty = beta[2] -> beta[2]
+           constraints = alpha ~ [beta]
+we don't quantify over beta (since it is fixed by envt)
+so we must promote it!  The inferred type is just
+  f :: beta -> beta
+
+NB: promoteTyVarSet ignores coercion variables
+
+Note [Defaulting during simplifyInfer]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When we are inferring a type, we simplify the constraint, and then use
+approximateWC to produce a list of candidate constraints.  Then we MUST
+
+  a) Promote any meta-tyvars that have been floated out by
+     approximateWC, to restore invariant (WantedInv) described in
+     Note [TcLevel invariants] in GHC.Tc.Utils.TcType.
+
+  b) Default the kind of any meta-tyvars that are not mentioned in
+     in the environment.
+
+To see (b), suppose the constraint is (C ((a :: OpenKind) -> Int)), and we
+have an instance (C ((x:*) -> Int)).  The instance doesn't match -- but it
+should!  If we don't solve the constraint, we'll stupidly quantify over
+(C (a->Int)) and, worse, in doing so skolemiseQuantifiedTyVar will quantify over
+(b:*) instead of (a:OpenKind), which can lead to disaster; see #7332.
+#7641 is a simpler example.
+
+-}
 
 -------------------
 defaultTyVarsAndSimplify :: TcLevel
@@ -1544,6 +1779,7 @@ defaultTyVarsAndSimplify :: TcLevel
                          -> TcM [PredType]      -- Guaranteed zonked
 -- Default any tyvar free in the constraints;
 -- and re-simplify in case the defaulting allows further simplification
+-- See Note [Defaulting during simplifyInfer]
 defaultTyVarsAndSimplify rhs_tclvl candidates
   = do {  -- Default any kind/levity vars
        ; DV {dv_kvs = cand_kvs, dv_tvs = cand_tvs}
@@ -1592,118 +1828,87 @@ decideQuantifiedTyVars skol_info name_taus psigs candidates
   = do {     -- Why psig_tys? We try to quantify over everything free in here
              -- See Note [Quantification and partial signatures]
              --     Wrinkles 2 and 3
-       ; (psig_tv_tys, psig_theta, tau_tys) <- TcM.liftZonkM $
-         do { psig_tv_tys <- mapM TcM.zonkTcTyVar [ tv | sig <- psigs
-                                                       , (_,Bndr tv _) <- sig_inst_skols sig ]
-            ; psig_theta  <- mapM TcM.zonkTcType [ pred | sig <- psigs
-                                                        , pred <- sig_inst_theta sig ]
-            ; tau_tys     <- mapM (TcM.zonkTcType . snd) name_taus
-            ; return (psig_tv_tys, psig_theta, tau_tys) }
-
-       ; let -- Try to quantify over variables free in these types
-             psig_tys = psig_tv_tys ++ psig_theta
-             seed_tys = psig_tys ++ tau_tys
-
-             -- Now "grow" those seeds to find ones reachable via 'candidates'
+         (psig_qtvs, psig_theta, tau_tys) <- getSeedTys name_taus psigs
+
+       ; let psig_tys = mkTyVarTys psig_qtvs ++ psig_theta
+             seed_tvs = tyCoVarsOfTypes (psig_tys ++ tau_tys)
+
+               -- "Grow" those seeds to find ones reachable via 'candidates'
              -- See Note [growThetaTyVars vs closeWrtFunDeps]
-             grown_tcvs = growThetaTyVars candidates (tyCoVarsOfTypes seed_tys)
+             grown_tcvs = growThetaTyVars candidates seed_tvs
 
        -- Now we have to classify them into kind variables and type variables
        -- (sigh) just for the benefit of -XNoPolyKinds; see quantifyTyVars
        --
-       -- Keep the psig_tys first, so that candidateQTyVarsOfTypes produces
-       -- them in that order, so that the final qtvs quantifies in the same
-       -- order as the partial signatures do (#13524)
-       ; dv at DV {dv_kvs = cand_kvs, dv_tvs = cand_tvs} <- candidateQTyVarsOfTypes $
-                                                         psig_tys ++ candidates ++ tau_tys
+       -- The psig_tys are first in seed_tys, then candidates, then tau_tvs.
+       -- This makes candidateQTyVarsOfTypes produces them in that order, so that the
+        -- final qtvs quantifies in the same- order as the partial signatures do (#13524)
+       ; dv at DV {dv_kvs = cand_kvs, dv_tvs = cand_tvs}
+             <- candidateQTyVarsOfTypes $
+                psig_tys ++ candidates ++ tau_tys
        ; let pick     = (`dVarSetIntersectVarSet` grown_tcvs)
              dvs_plus = dv { dv_kvs = pick cand_kvs, dv_tvs = pick cand_tvs }
 
        ; traceTc "decideQuantifiedTyVars" (vcat
-           [ text "tau_tys =" <+> ppr tau_tys
-           , text "candidates =" <+> ppr candidates
+           [ text "candidates =" <+> ppr candidates
            , text "cand_kvs =" <+> ppr cand_kvs
            , text "cand_tvs =" <+> ppr cand_tvs
-           , text "tau_tys =" <+> ppr tau_tys
-           , text "seed_tys =" <+> ppr seed_tys
-           , text "seed_tcvs =" <+> ppr (tyCoVarsOfTypes seed_tys)
+           , text "seed_tys =" <+> ppr seed_tvs
            , text "grown_tcvs =" <+> ppr grown_tcvs
            , text "dvs =" <+> ppr dvs_plus])
 
        ; quantifyTyVars skol_info DefaultNonStandardTyVars dvs_plus }
 
 ------------------
+getSeedTys :: [(Name,TcType)]    -- The type of each RHS in the group
+           -> [TcIdSigInst]      -- Any partial type signatures
+           -> TcM ( [TcTyVar]    -- Zonked partial-sig quantified tyvars
+                  , ThetaType    -- Zonked partial signature thetas
+                  , [TcType] )   -- Zonked tau-tys from the bindings
+getSeedTys name_taus psigs
+  = TcM.liftZonkM $
+    do { psig_tv_tys <- mapM TcM.zonkTcTyVar [ tv | TISI{ sig_inst_skols = skols } <- psigs
+                                                  , (_, Bndr tv _) <- skols ]
+       ; psig_theta  <- mapM TcM.zonkTcType [ pred | TISI{ sig_inst_theta = theta } <- psigs
+                                                   , pred <- theta ]
+       ; tau_tys     <- mapM (TcM.zonkTcType . snd) name_taus
+       ; return ( map getTyVar psig_tv_tys
+                , psig_theta
+                , tau_tys ) }
+
+------------------
+predMentions :: TcTyVarSet -> TcPredType -> Bool
+predMentions qtvs pred = tyCoVarsOfType pred `intersectsVarSet` qtvs
+
 -- | When inferring types, should we quantify over a given predicate?
 -- See Note [pickQuantifiablePreds]
 pickQuantifiablePreds
   :: TyVarSet           -- Quantifying over these
-  -> TcTyVarSet         -- mono_tvs0: variables mentioned a candidate
-                        --   constraint that come from some outer level
   -> TcThetaType        -- Proposed constraints to quantify
-  -> TcM TcThetaType    -- A subset that we can actually quantify
+  -> TcThetaType        -- A subset that we can actually quantify
 -- This function decides whether a particular constraint should be
 -- quantified over, given the type variables that are being quantified
-pickQuantifiablePreds qtvs mono_tvs0 theta
-  = do { tc_lvl <- TcM.getTcLevel
-       ; let is_nested = not (isTopTcLevel tc_lvl)
-       ; return (mkMinimalBySCs id $  -- See Note [Minimize by Superclasses]
-                 mapMaybe (pick_me is_nested) theta) }
+pickQuantifiablePreds qtvs theta
+  = mkMinimalBySCs id $  -- See Note [Minimize by Superclasses]
+    mapMaybe pick_me theta
   where
-    pick_me is_nested pred
-      = let pred_tvs = tyCoVarsOfType pred
-            mentions_qtvs = pred_tvs `intersectsVarSet` qtvs
-        in case classifyPredType pred of
-
-          ClassPred cls tys
-            | Just {} <- isCallStackPred cls tys
-              -- NEVER infer a CallStack constraint.  Otherwise we let
-              -- the constraints bubble up to be solved from the outer
-              -- context, or be defaulted when we reach the top-level.
-              -- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence
-            -> Nothing
-
+    pick_me pred
+      = case classifyPredType pred of
+          ClassPred cls _
             | isIPClass cls
-            -> Just pred -- See Note [Inheriting implicit parameters]
-
-            | not mentions_qtvs
-            -> Nothing   -- Don't quantify over predicates that don't
-                         -- mention any of the quantified type variables
-
-            | is_nested
-            -> Just pred
-
-            -- From here on, we are thinking about top-level defns only
-
-            | pred_tvs `subVarSet` (qtvs `unionVarSet` mono_tvs0)
-              -- See Note [Do not quantify over constraints that determine a variable]
-            -> Just pred
-
-            | otherwise
-            -> Nothing
+            -> Just pred -- Pick, say, (?x::Int) whether or not it mentions qtvs
+                         -- See Note [Inheriting implicit parameters]
 
           EqPred eq_rel ty1 ty2
-            | mentions_qtvs
-            , quantify_equality eq_rel ty1 ty2
+            | predMentions qtvs pred
             , Just (cls, tys) <- boxEqPred eq_rel ty1 ty2
               -- boxEqPred: See Note [Lift equality constraints when quantifying]
             -> Just (mkClassPred cls tys)
             | otherwise
             -> Nothing
 
-          IrredPred {} | mentions_qtvs -> Just pred
-                       | otherwise     -> Nothing
-
-          ForAllPred {} -> Nothing
-
-    -- See Note [Quantifying over equality constraints]
-    quantify_equality NomEq  ty1 ty2 = quant_fun ty1 || quant_fun ty2
-    quantify_equality ReprEq _   _   = True
-
-    quant_fun ty
-      = case tcSplitTyConApp_maybe ty of
-          Just (tc, tys) | isTypeFamilyTyCon tc
-                         -> tyCoVarsOfTypes tys `intersectsVarSet` qtvs
-          _ -> False
+          _ | predMentions qtvs pred -> Just pred
+            | otherwise              -> Nothing
 
 ------------------
 growThetaTyVars :: ThetaType -> TyCoVarSet -> TyCoVarSet
@@ -1725,24 +1930,8 @@ growThetaTyVars theta tcvs
          pred_tcvs = tyCoVarsOfType pred
 
 
-{- Note [Promote monomorphic tyvars]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Promote any type variables that are free in the environment.  Eg
-   f :: forall qtvs. bound_theta => zonked_tau
-The free vars of f's type become free in the envt, and hence will show
-up whenever 'f' is called.  They may currently at rhs_tclvl, but they
-had better be unifiable at the outer_tclvl!  Example: envt mentions
-alpha[1]
-           tau_ty = beta[2] -> beta[2]
-           constraints = alpha ~ [beta]
-we don't quantify over beta (since it is fixed by envt)
-so we must promote it!  The inferred type is just
-  f :: beta -> beta
-
-NB: promoteTyVarSet ignores coercion variables
-
-Note [pickQuantifiablePreds]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+{- Note [pickQuantifiablePreds]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 When pickQuantifiablePreds is called we have decided what type
 variables to quantify over, `qtvs`. The only quesion is: which of the
 unsolved candidate predicates should we quantify over?  Call them
@@ -1754,58 +1943,37 @@ For the members of unsolved_constraints that we select for picked_theta
 it is easy to solve, by identity.  For the others we just hope that
 we can solve them.
 
-So which of the candidates should we pick to quantify over?  In some
-situations we distinguish top-level from nested bindings.  The point
-about nested binding is that
- (a) the types may mention type variables free in the environment
- (b) all of the call sites are statically visible, reducing the
-     worries about "spooky action at a distance".
-
-First, never pick a constraint that doesn't mention any of the quantified
-variables `qtvs`.  Picking such a constraint essentially moves the solving of
-the constraint from this function definition to call sites.  But because the
-constraint mentions no quantified variables, call sites have no advantage
-over the definition site. Well, not quite: there could be new constraints
-brought into scope by a pattern-match against a constrained (e.g. GADT)
-constructor.  Example
-
-      data T a where { T1 :: T1 Bool; ... }
-
-      f :: forall a. a -> T a -> blah
-      f x t = let g y = x&&y    -- This needs a~Bool
-            in case t of
-                  T1 -> g True
-                  ....
-
-At g's call site we have `a~Bool`, so we /could/ infer
-     g :: forall . (a~Bool) => Bool -> Bool  -- qtvs = {}
-
-This is all very contrived, and probably just postponse type errors to
-the call site.  If that's what you want, write a type signature.
-
-Actually, implicit parameters is an exception to the "no quantified vars"
-rule (see Note [Inheriting implicit parameters]) so we can't actually
-simply test this case first.
-
-Now we consider the different sorts of constraints:
+So which of the candidates should we pick to quantify over?  It's pretty easy:
 
-* For ClassPred constraints:
+* Never pick a constraint that doesn't mention any of the quantified
+  variables `qtvs`.  Picking such a constraint essentially moves the solving of
+  the constraint from this function definition to call sites.  But because the
+  constraint mentions no quantified variables, call sites have no advantage
+  over the definition site. Well, not quite: there could be new constraints
+  brought into scope by a pattern-match against a constrained (e.g. GADT)
+  constructor.  Example
 
-  * Never pick a CallStack constraint.
-    See Note [Overview of implicit CallStacks]
+        data T a where { T1 :: T1 Bool; ... }
 
-  * Always pick an implicit-parameter constraint.
-    Note [Inheriting implicit parameters]
+        f :: forall a. a -> T a -> blah
+        f x t = let g y = x&&y    -- This needs a~Bool
+              in case t of
+                    T1 -> g True
+                    ....
 
-  * For /top-level/ class constraints see
-    Note [Do not quantify over constraints that determine a variable]
+  At g's call site we have `a~Bool`, so we /could/ infer
+       g :: forall . (a~Bool) => Bool -> Bool  -- qtvs = {}
 
-* For EqPred constraints see Note [Quantifying over equality constraints]
+  This is all very contrived, and probably just postponse type errors to
+  the call site.  If that's what you want, write a type signature.
 
-* For IrredPred constraints, we allow anything that mentions the quantified
-  type variables.
+* Implicit parameters is an exception to the "no quantified vars"
+  rule (see Note [Inheriting implicit parameters]) so we can't actually
+  simply test this case first.
 
-* A ForAllPred should not appear: the candidates come from approximateWC.
+* Finally, we may need to "box" equality predicates: if we want to quantify
+  over `a ~# b`, we actually quantify over the boxed version, `a ~ b`.
+  See Note [Lift equality constraints when quantifying].
 
 Notice that we do /not/ consult -XFlexibleContexts here.  For example,
 we allow `pickQuantifiablePreds` to quantify over a constraint like
@@ -1852,102 +2020,6 @@ parameters, *even if* they don't mention the bound type variables.
 Reason: because implicit parameters, uniquely, have local instance
 declarations. See pickQuantifiablePreds.
 
-Note [Quantifying over equality constraints]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Should we quantify over an equality constraint (s ~ t)
-in pickQuantifiablePreds?
-
-* It is always /sound/ to quantify over a constraint -- those
-  quantified constraints will need to be proved at each call site.
-
-* We definitely don't want to quantify over (Maybe a ~ Bool), to get
-     f :: forall a. (Maybe a ~ Bool) => blah
-  That simply postpones a type error from the function definition site to
-  its call site.  Fortunately we have already filtered out insoluble
-  constraints: see `definite_error` in `simplifyInfer`.
-
-* What about (a ~ T alpha b), where we are about to quantify alpha, `a` and
-  `b` are in-scope skolems, and `T` is a data type.  It's pretty unlikely
-  that this will be soluble at a call site, so we don't quantify over it.
-
-* What about `(F beta ~ Int)` where we are going to quantify `beta`?
-  Should we quantify over the (F beta ~ Int), to get
-     f :: forall b. (F b ~ Int) => blah
-  Aha!  Perhaps yes, because at the call site we will instantiate `b`, and
-  perhaps we have `instance F Bool = Int`. So we *do* quantify over a
-  type-family equality where the arguments mention the quantified variables.
-
-This is all a bit ad-hoc.
-
-Note [Do not quantify over constraints that determine a variable]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider (typecheck/should_compile/tc231), where we're trying to infer
-the type of a top-level declaration. We have
-  class Zork s a b | a -> b
-and the candidate constraint at the end of simplifyInfer is
-  [W] Zork alpha[1] (Z [Char]) beta[1]
-We definitely want to quantify over `alpha` (which is mentioned in the
-tau-type).
-
-But we do *not* want to quantify over `beta`: it is determined by the
-functional dependency on Zork: note that the second argument to Zork
-in the Wanted is a variable-free `Z [Char]`.  Quantifying over it
-would be "Henry Ford polymorphism".  (Presumably we don't have an
-instance in scope that tells us what `beta` actually is.)  Instead
-we promote `beta[1]` to `beta[0]`, in `decidePromotedTyVars`.
-
-The question here: do we want to quantify over the constraint, to
-give the type
-   forall a. Zork a (Z [Char]) beta[0] => blah
-Definitely not.  Since we're not quantifying over beta, it has been
-promoted; and then will be zapped to Any in the final zonk.  So we end
-up with a (perhaps exported) type involving
-  forall a. Zork a (Z [Char]) Any => blah
-No no no:
-
-  Key principle: we never want to show the programmer
-                 a type with `Any` in it.
-
-What we really want (to catch the Zork example) is this:
-
-   Quantify over the constraint only if all its free variables are
-   (a) quantified, or
-   (b) appears in the type of something in the environment (mono_tvs0).
-
-To understand (b) consider
-
-  class C a b where { op :: a -> b -> () }
-
-  mr = 3                      -- mr :: alpha
-  f1 x = op x mr              -- f1 :: forall b. b -> (), plus [W] C b alpha
-  intify = mr + (4 :: Int)
-
-In `f1` should we quantify over that `(C b alpha)`?  Answer: since `alpha`
-is free in the type envt, yes we should.  After all, if we'd typechecked
-`intify` first, we'd have set `alpha := Int`, and /then/ we'd certainly
-quantify.  The delicate Zork situation applies when beta is completely
-unconstrained (not free in the environment) -- except by the fundep.
-
-Another way to put it: let's say `alpha` is in `mono_tvs0`. It must be that
-some variable `x` has `alpha` free in its type. If we are at top-level (and we
-are, because nested decls don't go through this path all), then `x` must also
-be at top-level. And, by induction, `x` will not have Any in its type when all
-is said and done. The induction is well-founded because, if `x` is mutually
-recursive with the definition at hand, then their constraints get processed
-together (or `x` has a type signature, in which case the type doesn't have
-`Any`). So the key thing is that we must not introduce a new top-level
-unconstrained variable here.
-
-However this regrettably-subtle reasoning is needed only for /top-level/
-declarations.  For /nested/ decls we can see all the calls, so we'll
-instantiate that quantifed `Zork a (Z [Char]) beta` constraint at call sites,
-and either solve it or not (probably not).  We won't be left with a
-still-callable function with Any in its type.  So for nested definitions we
-don't make this tricky test.
-
-Historical note: we had a different, and more complicated test
-before, but it was utterly wrong: #23199.
-
 Note [Quantification and partial signatures]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 When choosing type variables to quantify, the basic plan is to
@@ -2177,63 +2249,4 @@ whatever, because the type-class defaulting rules have yet to run.
 
 An alternate implementation would be to emit a Wanted constraint setting
 the RuntimeRep variable to LiftedRep, but this seems unnecessarily indirect.
-
-Note [Promote _and_ default when inferring]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When we are inferring a type, we simplify the constraint, and then use
-approximateWC to produce a list of candidate constraints.  Then we MUST
-
-  a) Promote any meta-tyvars that have been floated out by
-     approximateWC, to restore invariant (WantedInv) described in
-     Note [TcLevel invariants] in GHC.Tc.Utils.TcType.
-
-  b) Default the kind of any meta-tyvars that are not mentioned in
-     in the environment.
-
-To see (b), suppose the constraint is (C ((a :: OpenKind) -> Int)), and we
-have an instance (C ((x:*) -> Int)).  The instance doesn't match -- but it
-should!  If we don't solve the constraint, we'll stupidly quantify over
-(C (a->Int)) and, worse, in doing so skolemiseQuantifiedTyVar will quantify over
-(b:*) instead of (a:OpenKind), which can lead to disaster; see #7332.
-#7641 is a simpler example.
-
-Note [Promoting unification variables]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When we float an equality out of an implication we must "promote" free
-unification variables of the equality, in order to maintain Invariant
-(WantedInv) from Note [TcLevel invariants] in GHC.Tc.Types.TcType.
-
-This is absolutely necessary. Consider the following example. We start
-with two implications and a class with a functional dependency.
-
-    class C x y | x -> y
-    instance C [a] [a]
-
-    (I1)      [untch=beta]forall b. 0 => F Int ~ [beta]
-    (I2)      [untch=beta]forall c. 0 => F Int ~ [[alpha]] /\ C beta [c]
-
-We float (F Int ~ [beta]) out of I1, and we float (F Int ~ [[alpha]]) out of I2.
-They may react to yield that (beta := [alpha]) which can then be pushed inwards
-the leftover of I2 to get (C [alpha] [a]) which, using the FunDep, will mean that
-(alpha := a). In the end we will have the skolem 'b' escaping in the untouchable
-beta! Concrete example is in indexed_types/should_fail/ExtraTcsUntch.hs:
-
-    class C x y | x -> y where
-     op :: x -> y -> ()
-
-    instance C [a] [a]
-
-    type family F a :: *
-
-    h :: F Int -> ()
-    h = undefined
-
-    data TEx where
-      TEx :: a -> TEx
-
-    f (x::beta) =
-        let g1 :: forall b. b -> ()
-            g1 _ = h [x]
-            g2 z = case z of TEx y -> (h [[undefined]], op x [y])
-        in (g1 '3', g2 undefined)
 -}


=====================================
compiler/GHC/Tc/Solver/Default.hs
=====================================
@@ -818,7 +818,11 @@ findDefaultableGroups (default_tys, extended_defaults) wanteds
     , defaultable_tyvar tv
     , defaultable_classes (map (classTyCon . sndOf3) group) ]
   where
-    simples                = approximateWC True wanteds
+    simples  = approximateWC True wanteds
+      -- True: for the purpose of defaulting we don't care
+      --       about shape or enclosing equalities
+      -- See (W3) in Note [ApproximateWC] in GHC.Tc.Types.Constraint
+
     (unaries, non_unaries) = partitionWith find_unary (bagToList simples)
     unary_groups           = equivClasses cmp_tv unaries
 


=====================================
compiler/GHC/Tc/Solver/Solve.hs
=====================================
@@ -73,9 +73,6 @@ simplifyWantedsTcM wanted
 
 solveWanteds :: WantedConstraints -> TcS WantedConstraints
 solveWanteds wc@(WC { wc_errors = errs })
-  | isEmptyWC wc  -- Fast path
-  = return wc
-  | otherwise
   = do { cur_lvl <- TcS.getTcLevel
        ; traceTcS "solveWanteds {" $
          vcat [ text "Level =" <+> ppr cur_lvl
@@ -106,6 +103,9 @@ simplify_loop :: Int -> IntWithInf -> Bool
 -- else, so we do them once, at the end in solveWanteds
 simplify_loop n limit definitely_redo_implications
               wc@(WC { wc_simple = simples, wc_impl = implics })
+  | isSolvedWC wc  -- Fast path
+  = return wc
+  | otherwise
   = do { csTraceTcS $
          text "simplify_loop iteration=" <> int n
          <+> (parens $ hsep [ text "definitely_redo =" <+> ppr definitely_redo_implications <> comma
@@ -145,7 +145,7 @@ maybe_simplify_again n limit unif_happened wc@(WC { wc_simple = simples })
   | unif_happened
   = simplify_loop n limit True wc
 
-  | superClassesMightHelp wc
+  | superClassesMightHelp wc    -- Returns False quickly if wc is solved
   = -- We still have unsolved goals, and apparently no way to solve them,
     -- so try expanding superclasses at this level, both Given and Wanted
     do { pending_given <- getPendingGivenScs


=====================================
compiler/GHC/Tc/TyCl/PatSyn.hs
=====================================
@@ -154,7 +154,7 @@ tcInferPatSynDecl (PSB { psb_id = lname@(L _ name), psb_args = details
 
        ; ((univ_tvs, req_dicts, ev_binds, _), residual)
                <- captureConstraints $
-                  simplifyInfer tclvl NoRestrictions [] named_taus wanted
+                  simplifyInfer TopLevel tclvl NoRestrictions [] named_taus wanted
        ; top_ev_binds <- checkNoErrs (simplifyTop residual)
        ; addTopEvBinds top_ev_binds $
 


=====================================
compiler/GHC/Tc/Types/Constraint.hs
=====================================
@@ -61,7 +61,7 @@ module GHC.Tc.Types.Constraint (
         tyCoVarsOfWC, tyCoVarsOfWCList,
         insolubleWantedCt, insolubleCt, insolubleIrredCt,
         insolubleImplic, nonDefaultableTyVarsOfWC,
-        approximateWC,
+        approximateWCX, approximateWC,
 
         Implication(..), implicationPrototype, checkTelescopeSkol,
         ImplicStatus(..), isInsolubleStatus, isSolvedStatus,
@@ -1815,60 +1815,121 @@ At the end, we will hopefully have substituted uf1 := F alpha, and we
 will be able to report a more informative error:
     'Can't construct the infinite type beta ~ F alpha beta'
 
+
 ************************************************************************
 *                                                                      *
-            Invariant checking (debug only)
+                     approximateWC
 *                                                                      *
 ************************************************************************
 -}
 
-approximateWC :: Bool   -- See Wrinkle (W3) in Note [ApproximateWC]
-              -> WantedConstraints
-              -> Cts
--- Second return value is the depleted wc
--- Postcondition: Wanted Cts
+type ApproxWC = ( Bag Ct    -- Free quantifiable constraints
+                , Bag Ct )  -- Free non-quantifiable constraints
+                            -- due to shape, or enclosing equality
+
+approximateWC :: Bool -> WantedConstraints -> Bag Ct
+approximateWC include_non_quantifiable cts
+  | include_non_quantifiable = quant `unionBags` no_quant
+  | otherwise                = quant
+  where
+    (quant, no_quant) = approximateWCX cts
+
+approximateWCX :: WantedConstraints -> ApproxWC
+-- The "X" means "extended";
+--    we return both quantifiable and non-quantifiable constraints
 -- See Note [ApproximateWC]
 -- See Note [floatKindEqualities vs approximateWC]
-approximateWC float_past_equalities wc
-  = float_wc False emptyVarSet wc
+approximateWCX wc
+  = float_wc False emptyVarSet wc (emptyBag, emptyBag)
   where
     float_wc :: Bool           -- True <=> there are enclosing equalities
              -> TcTyCoVarSet   -- Enclosing skolem binders
-             -> WantedConstraints -> Cts
-    float_wc encl_eqs trapping_tvs (WC { wc_simple = simples, wc_impl = implics })
-      = filterBag (is_floatable encl_eqs trapping_tvs) simples `unionBags`
-        concatMapBag (float_implic encl_eqs trapping_tvs) implics
-
-    float_implic :: Bool -> TcTyCoVarSet -> Implication -> Cts
+             -> WantedConstraints
+             -> ApproxWC -> ApproxWC
+    float_wc encl_eqs trapping_tvs (WC { wc_simple = simples, wc_impl = implics }) acc
+      = foldBag_flip (float_ct     encl_eqs trapping_tvs) simples $
+        foldBag_flip (float_implic encl_eqs trapping_tvs) implics $
+        acc
+
+    float_implic :: Bool -> TcTyCoVarSet -> Implication
+                 -> ApproxWC -> ApproxWC
     float_implic encl_eqs trapping_tvs imp
       = float_wc new_encl_eqs new_trapping_tvs (ic_wanted imp)
       where
         new_trapping_tvs = trapping_tvs `extendVarSetList` ic_skols imp
         new_encl_eqs = encl_eqs || ic_given_eqs imp == MaybeGivenEqs
 
-    is_floatable encl_eqs skol_tvs ct
-       | isGivenCt ct                                = False
-       | insolubleCt ct                              = False
-       | tyCoVarsOfCt ct `intersectsVarSet` skol_tvs = False
+    float_ct :: Bool -> TcTyCoVarSet -> Ct
+             -> ApproxWC -> ApproxWC
+    float_ct encl_eqs skol_tvs ct acc@(quant, no_quant)
+       | isGivenCt ct                                = acc
+           -- There can be (insoluble) Given constraints in wc_simple,
+           -- there so that we get error reports for unreachable code
+           -- See `given_insols` in GHC.Tc.Solver.Solve.solveImplication
+       | insolubleCt ct                              = acc
+       | tyCoVarsOfCt ct `intersectsVarSet` skol_tvs = acc
        | otherwise
        = case classifyPredType (ctPred ct) of
-           EqPred {}     -> float_past_equalities || not encl_eqs
-                                  -- See Wrinkle (W1)
-           ClassPred {}  -> True  -- See Wrinkle (W2)
-           IrredPred {}  -> True  -- ..both in Note [ApproximateWC]
-           ForAllPred {} -> False
+           -- See the classification in Note [ApproximateWC]
+           EqPred eq_rel ty1 ty2
+             | not encl_eqs      -- See Wrinkle (W1)
+             , quantify_equality eq_rel ty1 ty2
+             -> add_to_quant
+             | otherwise
+             -> add_to_no_quant
+
+           ClassPred cls tys
+             | Just {} <- isCallStackPred cls tys
+               -- NEVER infer a CallStack constraint.  Otherwise we let
+               -- the constraints bubble up to be solved from the outer
+               -- context, or be defaulted when we reach the top-level.
+               -- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence
+             -> add_to_no_quant
+
+             | otherwise
+             -> add_to_quant  -- See Wrinkle (W2)
+
+           IrredPred {}  -> add_to_quant  -- See Wrinkle (W2)
+
+           ForAllPred {} -> add_to_no_quant  -- Never quantify these
+       where
+         add_to_quant    = (ct `consBag` quant, no_quant)
+         add_to_no_quant = (quant, ct `consBag` no_quant)
+
+    -- See Note [Quantifying over equality constraints]
+    quantify_equality NomEq  ty1 ty2 = quant_fun ty1 || quant_fun ty2
+    quantify_equality ReprEq _   _   = True
+
+    quant_fun ty
+      = case tcSplitTyConApp_maybe ty of
+          Just (tc, _) -> isTypeFamilyTyCon tc
+          _              -> False
 
 {- Note [ApproximateWC]
 ~~~~~~~~~~~~~~~~~~~~~~~
 approximateWC takes a constraint, typically arising from the RHS of a
-let-binding whose type we are *inferring*, and extracts from it some
-*simple* constraints that we might plausibly abstract over.  Of course
-the top-level simple constraints are plausible, but we also float constraints
-out from inside, if they are not captured by skolems.
+let-binding whose type we are *inferring*, and extracts from it some *simple*
+constraints that we might plausibly abstract over.  Of course the top-level
+simple constraints are plausible, but we also float constraints out from inside,
+if they are not captured by skolems.
 
 The same function is used when doing type-class defaulting (see the call
 to applyDefaultingRules) to extract constraints that might be defaulted.
 
+We proceed by classifying the constraint:
+  * ClassPred:
+    * Never pick a CallStack constraint.
+      See Note [Overview of implicit CallStacks]
+    * Always pick an implicit-parameter constraint.
+      Note [Inheriting implicit parameters]
+    See wrinkle (W2)
+
+  * EqPred: see Note [Quantifying over equality constraints]
+
+  * IrredPred: we allow anything.
+
+  * ForAllPred: never quantify over these
+
 Wrinkle (W1)
   When inferring most-general types (in simplifyInfer), we
   do *not* float an equality constraint if the implication binds
@@ -1884,22 +1945,19 @@ Wrinkle (W1)
   non-principal types.)
 
 Wrinkle (W2)
-  We do allow /class/ constraints to float, even if
-  the implication binds equalities.  This is a subtle point: see #23224.
-  In principle, a class constraint might ultimately be satisfiable from
-  a constraint bound by an implication (see #19106 for an example of this
-  kind), but it's extremely obscure and I was unable to construct a
-  concrete example.  In any case, in super-subtle cases where this might
-  make a difference, you would be much better advised to simply write a
-  type signature.
-
-  I included IrredPred here too, for good measure.  In general,
-  abstracting over more constraints does no harm.
+  We do allow /class/ constraints to float, even if the implication binds
+  equalities.  This is a subtle point: see #23224.  In principle, a class
+  constraint might ultimately be satisfiable from a constraint bound by an
+  implication (see #19106 for an example of this kind), but it's extremely
+  obscure and I was unable to construct a concrete example.  In any case, in
+  super-subtle cases where this might make a difference, you would be much
+  better advised to simply write a type signature.
 
 Wrinkle (W3)
-  In findDefaultableGroups we are not worried about the
-  most-general type; and we /do/ want to float out of equalities
-  (#12797).  Hence the boolean flag to approximateWC.
+  In findDefaultableGroups we are not worried about the most-general type; and
+  we /do/ want to float out of equalities (#12797).  Hence we just union the two
+  returned lists.
+
 
 ------ Historical note -----------
 There used to be a second caveat, driven by #8155
@@ -1926,6 +1984,33 @@ you want.  So I simply removed the extra code to implement the
 contamination stuff.  There was zero effect on the testsuite (not even #8155).
 ------ End of historical note -----------
 
+Note [Quantifying over equality constraints]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Should we quantify over an equality constraint (s ~ t)
+in pickQuantifiablePreds?
+
+* It is always /sound/ to quantify over a constraint -- those
+  quantified constraints will need to be proved at each call site.
+
+* We definitely don't want to quantify over (Maybe a ~ Bool), to get
+     f :: forall a. (Maybe a ~ Bool) => blah
+  That simply postpones a type error from the function definition site to
+  its call site.  Fortunately we have already filtered out insoluble
+  constraints: see `definite_error` in `simplifyInfer`.
+
+* What about (a ~ T alpha b), where we are about to quantify alpha, `a` and
+  `b` are in-scope skolems, and `T` is a data type.  It's pretty unlikely
+  that this will be soluble at a call site, so we don't quantify over it.
+
+* What about `(F beta ~ Int)` where we are going to quantify `beta`?
+  Should we quantify over the (F beta ~ Int), to get
+     f :: forall b. (F b ~ Int) => blah
+  Aha!  Perhaps yes, because at the call site we will instantiate `b`, and
+  perhaps we have `instance F Bool = Int`. So we *do* quantify over a
+  type-family equality where the arguments mention the quantified variables.
+
+This is all a bit ad-hoc.
+
 
 ************************************************************************
 *                                                                      *


=====================================
compiler/GHC/Tc/Utils/TcMType.hs
=====================================
@@ -78,9 +78,8 @@ module GHC.Tc.Utils.TcMType (
   ---------------------------------
   -- Promotion, defaulting, skolemisation
   defaultTyVar, promoteMetaTyVarTo, promoteTyVarSet,
-  quantifyTyVars, isQuantifiableTv,
+  quantifyTyVars, doNotQuantifyTyVars,
   zonkAndSkolemise, skolemiseQuantifiedTyVar,
-  doNotQuantifyTyVars,
 
   candidateQTyVarsOfType,  candidateQTyVarsOfKind,
   candidateQTyVarsOfTypes, candidateQTyVarsOfKinds,
@@ -1788,15 +1787,6 @@ quantifyTyVars skol_info ns_strat dvs
       | otherwise
       = Just <$> skolemiseQuantifiedTyVar skol_info tkv
 
-isQuantifiableTv :: TcLevel   -- Level of the context, outside the quantification
-                 -> TcTyVar
-                 -> Bool
-isQuantifiableTv outer_tclvl tcv
-  | isTcTyVar tcv  -- Might be a CoVar; change this when gather covars separately
-  = tcTyVarLevel tcv `strictlyDeeperThan` outer_tclvl
-  | otherwise
-  = False
-
 zonkAndSkolemise :: SkolemInfo -> TcTyCoVar -> ZonkM TcTyCoVar
 -- A tyvar binder is never a unification variable (TauTv),
 -- rather it is always a skolem. It *might* be a TyVarTv.
@@ -2414,7 +2404,7 @@ promoteMetaTyVarTo :: HasDebugCallStack => TcLevel -> TcTyVar -> TcM Bool
 -- invariant (WantedInv) in Note [TcLevel invariants] in GHC.Tc.Utils.TcType
 -- Return True <=> we did some promotion
 -- Also returns either the original tyvar (no promotion) or the new one
--- See Note [Promoting unification variables]
+-- See Note [Promote monomorphic tyvars] in GHC.Tc.Solver
 promoteMetaTyVarTo tclvl tv
   | assertPpr (isMetaTyVar tv) (ppr tv) $
     tcTyVarLevel tv `strictlyDeeperThan` tclvl


=====================================
testsuite/tests/indexed-types/should_fail/ExtraTcsUntch.stderr
=====================================
@@ -1,12 +1,12 @@
 ExtraTcsUntch.hs:23:18: error: [GHC-83865]
     • Couldn't match expected type: F Int
-                  with actual type: [[a0]]
+                  with actual type: [p0]
     • In the first argument of ‘h’, namely ‘[x]’
       In the expression: h [x]
       In an equation for ‘g1’: g1 _ = h [x]
     • Relevant bindings include
-        x :: [a0] (bound at ExtraTcsUntch.hs:21:3)
-        f :: [a0] -> ((), ((), ())) (bound at ExtraTcsUntch.hs:21:1)
+        x :: p0 (bound at ExtraTcsUntch.hs:21:3)
+        f :: p0 -> ((), ((), ())) (bound at ExtraTcsUntch.hs:21:1)
 
 ExtraTcsUntch.hs:25:38: error: [GHC-83865]
     • Couldn't match expected type: F Int
@@ -14,7 +14,4 @@ ExtraTcsUntch.hs:25:38: error: [GHC-83865]
     • In the first argument of ‘h’, namely ‘[[undefined]]’
       In the expression: h [[undefined]]
       In the expression: (h [[undefined]], op x [y])
-    • Relevant bindings include
-        x :: [a0] (bound at ExtraTcsUntch.hs:21:3)
-        f :: [a0] -> ((), ((), ())) (bound at ExtraTcsUntch.hs:21:1)
 


=====================================
testsuite/tests/partial-sigs/should_fail/T10615.stderr
=====================================
@@ -1,34 +1,39 @@
 
 T10615.hs:5:7: error: [GHC-88464]
-    • Found type wildcard ‘_’ standing for ‘w1’
-      Where: ‘w1’ is an ambiguous type variable
+    • Found type wildcard ‘_’ standing for ‘w’
+      Where: ‘w’ is a rigid type variable bound by
+               the inferred type of f1 :: w -> f
+               at T10615.hs:6:1-10
       To use the inferred type, enable PartialTypeSignatures
     • In the type signature: f1 :: _ -> f
 
 T10615.hs:6:6: error: [GHC-25897]
-    • Couldn't match type ‘f’ with ‘b1 -> w1’
-      Expected: w1 -> f
-        Actual: w1 -> b1 -> w1
+    • Couldn't match type ‘f’ with ‘b1 -> w’
+      Expected: w -> f
+        Actual: w -> b1 -> w
       ‘f’ is a rigid type variable bound by
-        the inferred type of f1 :: w1 -> f
+        the inferred type of f1 :: w -> f
         at T10615.hs:5:1-12
     • In the expression: const
       In an equation for ‘f1’: f1 = const
-    • Relevant bindings include f1 :: w1 -> f (bound at T10615.hs:6:1)
+    • Relevant bindings include f1 :: w -> f (bound at T10615.hs:6:1)
 
 T10615.hs:8:7: error: [GHC-88464]
-    • Found type wildcard ‘_’ standing for ‘w0’
-      Where: ‘w0’ is an ambiguous type variable
+    • Found type wildcard ‘_’ standing for ‘w’
+      Where: ‘w’ is a rigid type variable bound by
+               the inferred type of f2 :: w -> _f
+               at T10615.hs:9:1-10
       To use the inferred type, enable PartialTypeSignatures
     • In the type signature: f2 :: _ -> _f
 
 T10615.hs:9:6: error: [GHC-25897]
-    • Couldn't match type ‘_f’ with ‘b0 -> w0’
-      Expected: w0 -> _f
-        Actual: w0 -> b0 -> w0
+    • Couldn't match type ‘_f’ with ‘b0 -> w’
+      Expected: w -> _f
+        Actual: w -> b0 -> w
       ‘_f’ is a rigid type variable bound by
-        the inferred type of f2 :: w0 -> _f
+        the inferred type of f2 :: w -> _f
         at T10615.hs:8:1-13
     • In the expression: const
       In an equation for ‘f2’: f2 = const
-    • Relevant bindings include f2 :: w0 -> _f (bound at T10615.hs:9:1)
+    • Relevant bindings include f2 :: w -> _f (bound at T10615.hs:9:1)
+


=====================================
testsuite/tests/polykinds/T14172.stderr
=====================================
@@ -1,7 +1,9 @@
 T14172.hs:7:46: error: [GHC-88464]
-    • Found type wildcard ‘_’ standing for ‘a'1 :: k0’
-      Where: ‘k0’ is an ambiguous type variable
-             ‘a'1’ is an ambiguous type variable
+    • Found type wildcard ‘_’ standing for ‘a'’
+      Where: ‘a'’ is a rigid type variable bound by
+               the inferred type of
+                 traverseCompose :: (a -> f b) -> g a -> f (h a')
+               at T14172.hs:8:1-46
       To use the inferred type, enable PartialTypeSignatures
     • In the first argument of ‘h’, namely ‘_’
       In the first argument of ‘f’, namely ‘(h _)’
@@ -10,19 +12,18 @@ T14172.hs:7:46: error: [GHC-88464]
 
 T14172.hs:8:19: error: [GHC-25897]
     • Couldn't match type ‘a’ with ‘g'1 a'0’
-      Expected: (f'0 a -> f (f'0 b)) -> g a -> f (h a'1)
-        Actual: (Unwrapped (Compose f'0 g'1 a'0)
-                 -> f (Unwrapped (h a'1)))
-                -> Compose f'0 g'1 a'0 -> f (h a'1)
+      Expected: (f'0 a -> f (f'0 b)) -> g a -> f (h a')
+        Actual: (Unwrapped (Compose f'0 g'1 a'0) -> f (Unwrapped (h a')))
+                -> Compose f'0 g'1 a'0 -> f (h a')
       ‘a’ is a rigid type variable bound by
         the inferred type of
-          traverseCompose :: (a -> f b) -> g a -> f (h a'1)
+          traverseCompose :: (a -> f b) -> g a -> f (h a')
         at T14172.hs:7:1-47
     • In the first argument of ‘(.)’, namely ‘_Wrapping Compose’
       In the expression: _Wrapping Compose . traverse
       In an equation for ‘traverseCompose’:
           traverseCompose = _Wrapping Compose . traverse
     • Relevant bindings include
-        traverseCompose :: (a -> f b) -> g a -> f (h a'1)
+        traverseCompose :: (a -> f b) -> g a -> f (h a')
           (bound at T14172.hs:8:1)
 


=====================================
testsuite/tests/typecheck/should_compile/T13785.hs
=====================================
@@ -2,15 +2,20 @@
 {-# OPTIONS_GHC -Wmonomorphism-restriction #-}
 module Bug where
 
-class Monad m => C m where
-  c :: (m Char, m Char)
+class Monad x => C x where
+  c :: (x Char, x Char)
 
 foo :: forall m. C m => m Char
-foo = bar >> baz >> bar2
+foo = bar >> baz >> bar1 >> bar2
   where
     -- Should not get MR warning
     bar, baz :: m Char
     (bar, baz) = c
 
+    -- Should not get MR warning
+    (bar1, baz1) = c :: (m Char, m Char)
+
     -- Should get MR warning
+    -- Natural type for the "whole binding": forall x. C x => (x Char, x Char)
+    -- MR makes it less polymorphic => warning.
     (bar2, baz2) = c


=====================================
testsuite/tests/typecheck/should_compile/T13785.stderr
=====================================
@@ -1,12 +1,13 @@
-
-T13785.hs:16:5: warning: [GHC-55524] [-Wmonomorphism-restriction]
+T13785.hs:21:5: warning: [GHC-55524] [-Wmonomorphism-restriction]
     • The Monomorphism Restriction applies to the bindings
       for ‘bar2’, ‘baz2’
     • In an equation for ‘foo’:
           foo
-            = bar >> baz >> bar2
+            = bar >> baz >> bar1 >> bar2
             where
                 bar, baz :: m Char
                 (bar, baz) = c
+                (bar1, baz1) = c :: (m Char, m Char)
                 (bar2, baz2) = c
     Suggested fix: Consider giving ‘baz2’ and ‘bar2’ a type signature
+


=====================================
testsuite/tests/typecheck/should_compile/T25266.hs
=====================================
@@ -0,0 +1,127 @@
+{-# OPTIONS_GHC -Wno-missing-methods #-}
+{-# LANGUAGE GHC2021 #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE ImplicitPrelude #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module GHC25266 where
+
+import Control.Monad.IO.Class (MonadIO (liftIO))
+import Control.Monad.Trans.Class (MonadTrans (lift))
+import Control.Monad.Trans.Reader (ReaderT, mapReaderT, runReaderT)
+import Data.Kind (Type)
+import Data.Void (Void)
+import GHC.Stack (HasCallStack, withFrozenCallStack)
+
+class MonadIO m => CanRunDB m where
+  unsafeUnlabelledRunDB :: HasCallStack => SqlPersistT m a -> m a
+
+type DBImpl backend env = ReaderT env (ReaderT backend IO)
+
+newtype DBWith backend env a = DB (DBImpl backend env a)
+  deriving newtype (Functor, Applicative, Monad)
+
+type DBEnv = ()
+
+type DB = DBWith SqlBackend DBEnv
+
+class Monad m => PersistentOperation m where
+  type PersistentBackend m
+  unsafeLiftPersistentOperation :: HasCallStack => ReaderT (PersistentBackend m) IO a -> m a
+
+instance PersistentOperation (DBWith backend env) where
+  type PersistentBackend (DBWith backend env) = backend
+  unsafeLiftPersistentOperation = DB . lift . checkpointCallStack
+
+toSqlPersistTIO :: env -> DBWith backend env a -> ReaderT backend IO a
+toSqlPersistTIO env (DB act) = runReaderT act env
+
+hoistIO :: MonadIO m => ReaderT backend IO a -> ReaderT backend m a
+hoistIO = mapReaderT liftIO
+
+liftToSqlPersistT :: forall m a backend. (CanRunDB m) => DBWith backend DBEnv a -> ReaderT backend m a
+liftToSqlPersistT action = do
+  let dbEnv = ()
+  hoistIO $ toSqlPersistTIO dbEnv action
+
+runDB :: (HasCallStack, CanRunDB m) => DB a -> m a
+runDB action = withFrozenCallStack unsafeUnlabelledRunDB $ liftToSqlPersistT action
+
+streamRows ::
+  forall m a.
+  (MonadUnliftIO m, CanRunDB m) =>
+  (forall n. (PersistentOperation n, PersistentBackend n ~ SqlBackend) => n [a]) ->
+  ConduitT () [a] m ()
+streamRows runQuery = go (10 :: Integer)
+  where
+    go n
+      | n < 0 = pure ()
+      | otherwise = do
+          rows <- lift . runDB $ runQuery
+          yield rows
+          go (n - 1)
+
+expectedList :: [Int]
+expectedList = [1, 2, 3]
+
+query :: forall n. (PersistentOperation n, PersistentBackend n ~ SqlBackend) => n [Int]
+query = pure expectedList
+
+test_success :: forall m. (MonadUnliftIO m, CanRunDB m) => m [[Int]]
+test_success = do
+  let conduit = streamRows query .| (sinkList @_ @[Int])
+  runConduit conduit
+
+test_fail :: forall m. (MonadUnliftIO m, CanRunDB m) => m [[Int]]
+test_fail = do
+  let conduit = streamRows query .| sinkList
+  runConduit conduit
+
+-----
+-- annotated-exception
+-----
+
+checkpointCallStack
+    -- :: (MonadCatch m, HasCallStack)
+    :: (Monad m, HasCallStack)
+    => m a
+    -> m a
+checkpointCallStack = id
+
+-----
+-- conduit
+-----
+
+data ConduitT i o (m :: Type -> Type) r
+instance Functor (ConduitT i o m)
+instance Applicative (ConduitT i o m)
+instance Monad (ConduitT i o m)
+instance MonadTrans (ConduitT i o)
+
+(.|) :: Monad m => ConduitT a b m () -> ConduitT b c m r -> ConduitT a c m r
+(.|) = undefined
+
+runConduit :: Monad m => ConduitT () Void m r -> m r
+runConduit = undefined
+
+sinkList :: Monad m => ConduitT a o m [a]
+sinkList = undefined
+
+yield :: Monad m => o -> ConduitT i o m ()
+yield = undefined
+
+-----
+-- persistent
+-----
+
+data SqlBackend
+
+type SqlPersistT = ReaderT SqlBackend
+
+-----
+-- unliftio
+-----
+
+class MonadIO m => MonadUnliftIO m where
+  withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b


=====================================
testsuite/tests/typecheck/should_compile/T25266a.hs
=====================================
@@ -0,0 +1,13 @@
+{-# LANGUAGE GADTs #-}
+
+module T25266a where
+
+data T a where { T1 :: T Int; T2 :: a -> T a }
+
+-- Rejected, becuase there is no principal type,
+-- and the function is top level
+f x y t = (case t of
+                      T1   -> length [x,y]
+                      T2 _ -> 2)  :: Int
+
+


=====================================
testsuite/tests/typecheck/should_compile/T25266a.stderr
=====================================
@@ -0,0 +1,21 @@
+T25266a.hs:10:41: error: [GHC-25897]
+    • Could not deduce ‘p1 ~ p2’
+      from the context: a ~ Int
+        bound by a pattern with constructor: T1 :: T Int,
+                 in a case alternative
+        at T25266a.hs:10:23-24
+      ‘p1’ is a rigid type variable bound by
+        the inferred type of f :: p1 -> p2 -> T a -> Int
+        at T25266a.hs:(9,1)-(11,40)
+      ‘p2’ is a rigid type variable bound by
+        the inferred type of f :: p1 -> p2 -> T a -> Int
+        at T25266a.hs:(9,1)-(11,40)
+    • In the expression: y
+      In the first argument of ‘length’, namely ‘[x, y]’
+      In the expression: length [x, y]
+    • Relevant bindings include
+        y :: p2 (bound at T25266a.hs:9:5)
+        x :: p1 (bound at T25266a.hs:9:3)
+        f :: p1 -> p2 -> T a -> Int (bound at T25266a.hs:9:1)
+    Suggested fix: Consider giving ‘f’ a type signature
+


=====================================
testsuite/tests/typecheck/should_compile/T25266b.hs
=====================================
@@ -0,0 +1,15 @@
+{-# LANGUAGE GADTs #-}
+
+module T25266b where
+
+data T a where { T1 :: T Int; T2 :: a -> T a }
+
+h :: Int -> (Int,Int)
+-- Binding for `f` is accepted; we do not generalise it
+--     f :: forall a. alpha -> beta -> T a -> Int
+-- We figure out alpha/beta from the call sites
+h p = let f x y t = (case t of
+                      T1   -> length [x,y]
+                      T2 _ -> 2)  :: Int
+      in (f p (4::Int) (T2 'c'), f 4 5 (T2 "oooh"))
+


=====================================
testsuite/tests/typecheck/should_compile/all.T
=====================================
@@ -934,4 +934,7 @@ test('T25125', normal, compile, [''])
 test('T24845a', normal, compile, [''])
 test('T23501a', normal, compile, [''])
 test('T23501b', normal, compile, [''])
+test('T25266', normal, compile, [''])
+test('T25266a', normal, compile_fail, [''])
+test('T25266b', normal, compile, [''])
 


=====================================
testsuite/tests/typecheck/should_fail/T18398.stderr
=====================================
@@ -6,7 +6,7 @@ T18398.hs:13:34: error: [GHC-39999]
       In the expression: case x of MkEx _ -> meth x y
 
 T18398.hs:13:70: error: [GHC-39999]
-    • No instance for ‘C Ex t0’ arising from a use of ‘meth’
+    • No instance for ‘C Ex t1’ arising from a use of ‘meth’
     • In the expression: meth x z
       In a case alternative: MkEx _ -> meth x z
       In the expression: case x of MkEx _ -> meth x z



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3fb9764f14acab1c3082cd98842eee6e6e110c44

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3fb9764f14acab1c3082cd98842eee6e6e110c44
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/20241017/52c1e3d0/attachment-0001.html>


More information about the ghc-commits mailing list