Simon Peyton Jones pushed to branch wip/T26115 at Glasgow Haskell Compiler / GHC
Commits:
-
ff3f98d1
by Simon Peyton Jones at 2025-06-24T16:16:23+01:00
7 changed files:
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types/Evidence.hs
Changes:
... | ... | @@ -1181,8 +1181,8 @@ dsSpec_help poly_nm poly_id poly_rhs spec_inl orig_bndrs ds_call |
1181 | 1181 | |
1182 | 1182 | mk_spec_body fn_body = mkLets (rn_binds ++ picked_binds) $
|
1183 | 1183 | mkApps fn_body rule_lhs_args
|
1184 | - -- ToDo: not mkCoreApps! That uses exprType on fun which
|
|
1185 | - -- fails in specUnfolding, sigh
|
|
1184 | + -- NB: not mkCoreApps! That uses exprType on fun
|
|
1185 | + -- which fails in specUnfolding, sigh
|
|
1186 | 1186 | |
1187 | 1187 | poly_name = idName poly_id
|
1188 | 1188 | spec_occ = mkSpecOcc (getOccName poly_name)
|
... | ... | @@ -622,7 +622,8 @@ reportWanteds ctxt tc_lvl wc@(WC { wc_simple = simples, wc_impl = implics |
622 | 622 | -- report2: we suppress these if there are insolubles elsewhere in the tree
|
623 | 623 | report2 = [ ("Implicit params", is_ip, False, mkGroupReporter mkIPErr)
|
624 | 624 | , ("Irreds", is_irred, False, mkGroupReporter mkIrredErr)
|
625 | - , ("Dicts", is_dict, False, mkGroupReporter mkDictErr) ]
|
|
625 | + , ("Dicts", is_dict, False, mkGroupReporter mkDictErr)
|
|
626 | + , ("Quantified", is_qc, False, mkGroupReporter mkQCErr) ]
|
|
626 | 627 | |
627 | 628 | -- report3: suppressed errors should be reported as categorized by either report1
|
628 | 629 | -- or report2. Keep this in sync with the suppress function above
|
... | ... | @@ -681,6 +682,9 @@ reportWanteds ctxt tc_lvl wc@(WC { wc_simple = simples, wc_impl = implics |
681 | 682 | is_irred _ (IrredPred {}) = True
|
682 | 683 | is_irred _ _ = False
|
683 | 684 | |
685 | + is_qc _ (ForAllPred {}) = True
|
|
686 | + is_qc _ _ = False
|
|
687 | + |
|
684 | 688 | -- See situation (1) of Note [Suppressing confusing errors]
|
685 | 689 | is_ww_fundep item _ = is_ww_fundep_item item
|
686 | 690 | is_ww_fundep_item = isWantedWantedFunDepOrigin . errorItemOrigin
|
... | ... | @@ -2175,6 +2179,13 @@ Warn of loopy local equalities that were dropped. |
2175 | 2179 | ************************************************************************
|
2176 | 2180 | -}
|
2177 | 2181 | |
2182 | +mkQCErr :: HasDebugCallStack => SolverReportErrCtxt -> NonEmpty ErrorItem -> TcM SolverReport
|
|
2183 | +mkQCErr ctxt items
|
|
2184 | + = do { let msg = mkPlainMismatchMsg $
|
|
2185 | + CouldNotDeduce (getUserGivens ctxt) items Nothing
|
|
2186 | + ; return $ important ctxt msg }
|
|
2187 | + |
|
2188 | + |
|
2178 | 2189 | mkDictErr :: HasDebugCallStack => SolverReportErrCtxt -> NonEmpty ErrorItem -> TcM SolverReport
|
2179 | 2190 | mkDictErr ctxt orig_items
|
2180 | 2191 | = do { inst_envs <- tcGetInstEnvs
|
... | ... | @@ -2192,8 +2203,8 @@ mkDictErr ctxt orig_items |
2192 | 2203 | ; return $
|
2193 | 2204 | SolverReport
|
2194 | 2205 | { sr_important_msg = SolverReportWithCtxt ctxt err
|
2195 | - , sr_supplementary =
|
|
2196 | - [ SupplementaryImportErrors imps | imps <- maybeToList (NE.nonEmpty imp_errs) ]
|
|
2206 | + , sr_supplementary = [ SupplementaryImportErrors imps
|
|
2207 | + | imps <- maybeToList (NE.nonEmpty imp_errs) ]
|
|
2197 | 2208 | , sr_hints = hints
|
2198 | 2209 | }
|
2199 | 2210 | }
|
... | ... | @@ -701,7 +701,12 @@ and Given/instance fundeps entirely. |
701 | 701 | tryInertDicts :: DictCt -> SolverStage ()
|
702 | 702 | tryInertDicts dict_ct
|
703 | 703 | = Stage $ do { inerts <- getInertCans
|
704 | - ; try_inert_dicts inerts dict_ct }
|
|
704 | + ; mode <- getTcSMode
|
|
705 | + -- In TcSSpecPrag mode we do not look at Givens; that's the point
|
|
706 | + -- Looking at Wanteds would be OK but no real benefit
|
|
707 | + ; case mode of
|
|
708 | + TcSSpecPrag -> continueWith ()
|
|
709 | + _other -> try_inert_dicts inerts dict_ct }
|
|
705 | 710 | |
706 | 711 | try_inert_dicts :: InertCans -> DictCt -> TcS (StopOrContinue ())
|
707 | 712 | try_inert_dicts inerts dict_w@(DictCt { di_ev = ev_w, di_cls = cls, di_tys = tys })
|
... | ... | @@ -767,22 +772,15 @@ tryShortCutSolver try_short_cut dict_w@(DictCt { di_ev = ev_w }) |
767 | 772 | -- Enabled by the -fsolve-constant-dicts flag
|
768 | 773 | |
769 | 774 | -> tryTcS $ -- tryTcS tries to completely solve some contraints
|
775 | + -- Inherit the current solved_dicts, so that one invocation of
|
|
776 | + -- tryShortCutSolver can benefit from the work of earlier invocations
|
|
770 | 777 | setTcSMode TcSSpecPrag $
|
771 | - do { updInertSet zap_cans
|
|
772 | - ; solveSimpleWanteds (unitBag (CDictCan dict_w)) }
|
|
778 | + do { wc <- solveSimpleWanteds (unitBag (CDictCan dict_w))
|
|
779 | + ; return (isSolvedWC wc) }
|
|
773 | 780 | |
774 | 781 | | otherwise
|
775 | 782 | -> return False }
|
776 | 783 | |
777 | - where
|
|
778 | - zap_cans :: InertSet -> InertSet
|
|
779 | - -- Zap the inert Givens (so we don't try to use them for solving)
|
|
780 | - -- and any inert Wanteds (no harm but not much benefit either.
|
|
781 | - -- But preserve the current solved_dicts, so that one invocation of
|
|
782 | - -- tryShortCutSolver can benefit from the work of earlier invocations
|
|
783 | - zap_cans inerts@(IS { inert_cans = cans })
|
|
784 | - = inerts { inert_cans = emptyInertCans (inert_given_eq_lvl cans) }
|
|
785 | - |
|
786 | 784 | |
787 | 785 | {- *******************************************************************
|
788 | 786 | * *
|
... | ... | @@ -27,7 +27,6 @@ module GHC.Tc.Solver.InertSet ( |
27 | 27 | foldTyEqs, delEq, findEq,
|
28 | 28 | partitionInertEqs, partitionFunEqs,
|
29 | 29 | filterInertEqs, filterFunEqs,
|
30 | - inertGivens,
|
|
31 | 30 | foldFunEqs, addEqToCans,
|
32 | 31 | |
33 | 32 | -- * Inert Dicts
|
... | ... | @@ -347,6 +346,10 @@ data InertSet |
347 | 346 | -- Canonical Given, Wanted
|
348 | 347 | -- Sometimes called "the inert set"
|
349 | 348 | |
349 | + , inert_givens :: InertCans
|
|
350 | + -- A subset of inert_cans, containing only Givens
|
|
351 | + -- Used to initialise inert_cans when recursing inside implications
|
|
352 | + |
|
350 | 353 | , inert_cycle_breakers :: CycleBreakerVarStack
|
351 | 354 | |
352 | 355 | , inert_famapp_cache :: FunEqMap Reduction
|
... | ... | @@ -399,11 +402,14 @@ emptyInertCans given_eq_lvl |
399 | 402 | |
400 | 403 | emptyInertSet :: TcLevel -> InertSet
|
401 | 404 | emptyInertSet given_eq_lvl
|
402 | - = IS { inert_cans = emptyInertCans given_eq_lvl
|
|
405 | + = IS { inert_cans = empty_cans
|
|
406 | + , inert_givens = empty_cans
|
|
403 | 407 | , inert_cycle_breakers = emptyBag :| []
|
404 | 408 | , inert_famapp_cache = emptyFunEqs
|
405 | 409 | , inert_solved_dicts = emptyDictMap
|
406 | - , inert_safehask = emptyDictMap }
|
|
410 | + , inert_safehask = emptyDictMap }
|
|
411 | + where
|
|
412 | + empty_cans = emptyInertCans given_eq_lvl
|
|
407 | 413 | |
408 | 414 | {- Note [Solved dictionaries]
|
409 | 415 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
... | ... | @@ -2129,43 +2135,3 @@ Wrong! The level-check ensures that the inner implicit parameter wins. |
2129 | 2135 | that this chain of events won't happen, but that's very fragile.)
|
2130 | 2136 | -}
|
2131 | 2137 | |
2132 | -{- *********************************************************************
|
|
2133 | -* *
|
|
2134 | - Extracting Givens from the inert set
|
|
2135 | -* *
|
|
2136 | -********************************************************************* -}
|
|
2137 | - |
|
2138 | - |
|
2139 | --- | Extract only Given constraints from the inert set.
|
|
2140 | -inertGivens :: InertSet -> InertSet
|
|
2141 | -inertGivens is@(IS { inert_cans = cans, inert_safehask = safehask }) =
|
|
2142 | - is { inert_cans = givens_cans
|
|
2143 | - , inert_safehask = safehask_givens
|
|
2144 | - , inert_solved_dicts = emptyDictMap
|
|
2145 | - }
|
|
2146 | - where
|
|
2147 | - |
|
2148 | - isGivenEq :: EqCt -> Bool
|
|
2149 | - isGivenEq eq = isGiven (ctEvidence (CEqCan eq))
|
|
2150 | - isGivenDict :: DictCt -> Bool
|
|
2151 | - isGivenDict dict = isGiven (ctEvidence (CDictCan dict))
|
|
2152 | - isGivenIrred :: IrredCt -> Bool
|
|
2153 | - isGivenIrred irred = isGiven (ctEvidence (CIrredCan irred))
|
|
2154 | - |
|
2155 | - -- Filter the inert constraints for Givens
|
|
2156 | - (eq_givens_list, _) = partitionInertEqs isGivenEq (inert_eqs cans)
|
|
2157 | - (funeq_givens_list, _) = partitionFunEqs isGivenEq (inert_funeqs cans)
|
|
2158 | - dict_givens = filterDicts isGivenDict (inert_dicts cans)
|
|
2159 | - safehask_givens = filterDicts isGivenDict safehask
|
|
2160 | - irreds_givens = filterBag isGivenIrred (inert_irreds cans)
|
|
2161 | - |
|
2162 | - eq_givens = foldr addInertEqs emptyTyEqs eq_givens_list
|
|
2163 | - funeq_givens = foldr addFunEqs emptyFunEqs funeq_givens_list
|
|
2164 | - |
|
2165 | - givens_cans =
|
|
2166 | - cans
|
|
2167 | - { inert_eqs = eq_givens
|
|
2168 | - , inert_funeqs = funeq_givens
|
|
2169 | - , inert_dicts = dict_givens
|
|
2170 | - , inert_irreds = irreds_givens
|
|
2171 | - } |
... | ... | @@ -1293,27 +1293,21 @@ nestImplicTcS :: EvBindsVar |
1293 | 1293 | -> TcLevel -> TcS a
|
1294 | 1294 | -> TcS a
|
1295 | 1295 | nestImplicTcS ref inner_tclvl (TcS thing_inside)
|
1296 | - = TcS $ \ TcSEnv { tcs_unified = unified_var
|
|
1297 | - , tcs_inerts = old_inert_var
|
|
1298 | - , tcs_count = count
|
|
1299 | - , tcs_unif_lvl = unif_lvl
|
|
1300 | - , tcs_mode = mode
|
|
1301 | - } ->
|
|
1296 | + = TcS $ \ env@(TcSEnv { tcs_inerts = old_inert_var }) ->
|
|
1302 | 1297 | do { inerts <- TcM.readTcRef old_inert_var
|
1298 | + |
|
1299 | + -- Initialise the inert_cans from the inert_givens of the parent
|
|
1300 | + -- so that the child is not polluted with the parent's inert Wanteds
|
|
1303 | 1301 | ; let nest_inert = inerts { inert_cycle_breakers = pushCycleBreakerVarStack
|
1304 | 1302 | (inert_cycle_breakers inerts)
|
1305 | - , inert_cans = (inert_cans inerts)
|
|
1303 | + , inert_cans = (inert_givens inerts)
|
|
1306 | 1304 | { inert_given_eqs = False } }
|
1307 | 1305 | -- All other InertSet fields are inherited
|
1308 | 1306 | ; new_inert_var <- TcM.newTcRef nest_inert
|
1309 | 1307 | ; new_wl_var <- TcM.newTcRef emptyWorkList
|
1310 | - ; let nest_env = TcSEnv { tcs_count = count -- Inherited
|
|
1311 | - , tcs_unif_lvl = unif_lvl -- Inherited
|
|
1312 | - , tcs_ev_binds = ref
|
|
1313 | - , tcs_unified = unified_var
|
|
1314 | - , tcs_inerts = new_inert_var
|
|
1315 | - , tcs_mode = mode
|
|
1316 | - , tcs_worklist = new_wl_var }
|
|
1308 | + ; let nest_env = env { tcs_ev_binds = ref
|
|
1309 | + , tcs_inerts = new_inert_var
|
|
1310 | + , tcs_worklist = new_wl_var }
|
|
1317 | 1311 | ; res <- TcM.setTcLevel inner_tclvl $
|
1318 | 1312 | thing_inside nest_env
|
1319 | 1313 | |
... | ... | @@ -1339,6 +1333,7 @@ nestTcS (TcS thing_inside) |
1339 | 1333 | ; new_wl_var <- TcM.newTcRef emptyWorkList
|
1340 | 1334 | ; let nest_env = env { tcs_inerts = new_inert_var
|
1341 | 1335 | , tcs_worklist = new_wl_var }
|
1336 | + -- Inherit tcs_ev_binds from caller
|
|
1342 | 1337 | |
1343 | 1338 | ; res <- thing_inside nest_env
|
1344 | 1339 | |
... | ... | @@ -1347,18 +1342,17 @@ nestTcS (TcS thing_inside) |
1347 | 1342 | |
1348 | 1343 | ; return res }
|
1349 | 1344 | |
1350 | -tryTcS :: TcS WantedConstraints -> TcS Bool
|
|
1345 | +tryTcS :: TcS Bool -> TcS Bool
|
|
1351 | 1346 | -- Like nestTcS, but
|
1352 | 1347 | -- (a) be a no-op if the nested computation returns Nothing
|
1353 | 1348 | -- (b) if (but only if) success, propagate nested bindings to the caller
|
1354 | 1349 | tryTcS (TcS thing_inside)
|
1355 | 1350 | = TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var
|
1356 | - , tcs_ev_binds = old_ev_binds_var
|
|
1357 | - , tcs_worklist = wl_var }) ->
|
|
1351 | + , tcs_ev_binds = old_ev_binds_var }) ->
|
|
1358 | 1352 | do { old_inerts <- TcM.readTcRef inerts_var
|
1359 | 1353 | ; new_inert_var <- TcM.newTcRef old_inerts
|
1360 | 1354 | ; new_wl_var <- TcM.newTcRef emptyWorkList
|
1361 | - ; new_ev_binds_var <- TcM.newTcEvBinds
|
|
1355 | + ; new_ev_binds_var <- TcM.cloneEvBindsVar old_ev_binds_var
|
|
1362 | 1356 | ; let nest_env = env { tcs_ev_binds = new_ev_binds_var
|
1363 | 1357 | , tcs_inerts = new_inert_var
|
1364 | 1358 | , tcs_worklist = new_wl_var }
|
... | ... | @@ -1367,10 +1361,10 @@ tryTcS (TcS thing_inside) |
1367 | 1361 | vcat [ text "old_ev_binds:" <+> ppr old_ev_binds_var
|
1368 | 1362 | , text "new_ev_binds:" <+> ppr new_ev_binds_var
|
1369 | 1363 | , ppr old_inerts ]
|
1370 | - ; wc <- thing_inside nest_env
|
|
1371 | - ; TcM.traceTc "tryTcS }" (ppr wc)
|
|
1364 | + ; solved <- thing_inside nest_env
|
|
1365 | + ; TcM.traceTc "tryTcS }" (ppr solved)
|
|
1372 | 1366 | |
1373 | - ; if not (isSolvedWC wc)
|
|
1367 | + ; if not solved
|
|
1374 | 1368 | then return False
|
1375 | 1369 | else do { -- Successfully solved
|
1376 | 1370 | -- Add the new bindings to the existing ones
|
... | ... | @@ -1382,17 +1376,12 @@ tryTcS (TcS thing_inside) |
1382 | 1376 | |
1383 | 1377 | ; TcM.traceTc "tryTcS update" (ppr (inert_solved_dicts new_inerts))
|
1384 | 1378 | |
1385 | - -- We **must not** drop solved implications, due
|
|
1386 | - -- to Note [Free vars of EvFun] in GHC.Tc.Types.Evidence;
|
|
1387 | - -- so we re-emit them here.
|
|
1388 | - ; TcM.updTcRef wl_var (extendWorkListImplics (wc_impl wc))
|
|
1389 | - |
|
1390 | 1379 | ; return True } }
|
1391 | 1380 | |
1392 | 1381 | updateInertsWith :: InertSet -> InertSet -> InertSet
|
1393 | 1382 | -- Update the current inert set with bits from a nested solve,
|
1394 | 1383 | -- that finished with a new inert set
|
1395 | --- In particular, propagage:
|
|
1384 | +-- In particular, propagate:
|
|
1396 | 1385 | -- - solved dictionaires; see Note [Propagate the solved dictionaries]
|
1397 | 1386 | -- - Safe Haskell failures
|
1398 | 1387 | updateInertsWith current_inerts
|
... | ... | @@ -280,6 +280,20 @@ solveNestedImplications implics |
280 | 280 | |
281 | 281 | ; return unsolved_implics }
|
282 | 282 | |
283 | +trySolveImplication :: Implication -> TcS Bool
|
|
284 | +trySolveImplication (Implic { ic_tclvl = tclvl
|
|
285 | + , ic_binds = ev_binds_var
|
|
286 | + , ic_given = given_ids
|
|
287 | + , ic_wanted = wanteds
|
|
288 | + , ic_env = ct_loc_env
|
|
289 | + , ic_info = info })
|
|
290 | + = nestImplicTcS ev_binds_var tclvl $
|
|
291 | + do { let loc = mkGivenLoc tclvl info ct_loc_env
|
|
292 | + givens = mkGivens loc given_ids
|
|
293 | + ; solveSimpleGivens givens
|
|
294 | + ; residual_wanted <- solveWanteds wanteds
|
|
295 | + ; return (isSolvedWC residual_wanted) }
|
|
296 | + |
|
283 | 297 | solveImplication :: Implication -- Wanted
|
284 | 298 | -> TcS Implication -- Simplified implication
|
285 | 299 | -- Precondition: The TcS monad contains an empty worklist and given-only inerts
|
... | ... | @@ -289,6 +303,7 @@ solveImplication imp@(Implic { ic_tclvl = tclvl |
289 | 303 | , ic_given = given_ids
|
290 | 304 | , ic_wanted = wanteds
|
291 | 305 | , ic_info = info
|
306 | + , ic_env = ct_loc_env
|
|
292 | 307 | , ic_status = status })
|
293 | 308 | | isSolvedStatus status
|
294 | 309 | = return imp -- Do nothing
|
... | ... | @@ -306,7 +321,7 @@ solveImplication imp@(Implic { ic_tclvl = tclvl |
306 | 321 | -- Solve the nested constraints
|
307 | 322 | ; (has_given_eqs, given_insols, residual_wanted)
|
308 | 323 | <- nestImplicTcS ev_binds_var tclvl $
|
309 | - do { let loc = mkGivenLoc tclvl info (ic_env imp)
|
|
324 | + do { let loc = mkGivenLoc tclvl info ct_loc_env
|
|
310 | 325 | givens = mkGivens loc given_ids
|
311 | 326 | ; solveSimpleGivens givens
|
312 | 327 | |
... | ... | @@ -958,6 +973,11 @@ solveSimpleGivens givens |
958 | 973 | | otherwise
|
959 | 974 | = do { traceTcS "solveSimpleGivens {" (ppr givens)
|
960 | 975 | ; go givens
|
976 | + |
|
977 | + -- Capture the Givens in the inert_givens of the inert set
|
|
978 | + -- for use by subsequent calls of nestImplicTcS
|
|
979 | + ; updInertSet (\is -> is { inert_givens = inert_cans is })
|
|
980 | + |
|
961 | 981 | ; traceTcS "End solveSimpleGivens }" empty }
|
962 | 982 | where
|
963 | 983 | go givens = do { solveSimples (listToBag givens)
|
... | ... | @@ -1348,7 +1368,7 @@ solveWantedForAll qci tvs theta body_pred |
1348 | 1368 | ; return ( wantedCtEvEvId wanted_ev
|
1349 | 1369 | , unitBag (mkNonCanonical $ CtWanted wanted_ev)) }
|
1350 | 1370 | |
1351 | - ; traceTcS "solveForAll" (ppr given_ev_vars $$ ppr wanteds $$ ppr w_id)
|
|
1371 | + ; traceTcS "solveForAll {" (ppr skol_tvs $$ ppr given_ev_vars $$ ppr wanteds $$ ppr w_id)
|
|
1352 | 1372 | ; ev_binds_var <- TcS.newTcEvBinds
|
1353 | 1373 | ; solved <- trySolveImplication $
|
1354 | 1374 | (implicationPrototype loc_env)
|
... | ... | @@ -1359,6 +1379,7 @@ solveWantedForAll qci tvs theta body_pred |
1359 | 1379 | , ic_skols = skol_tvs
|
1360 | 1380 | , ic_given = given_ev_vars
|
1361 | 1381 | , ic_wanted = emptyWC { wc_simple = wanteds } }
|
1382 | + ; traceTcS "sllveForAll }" (ppr solved)
|
|
1362 | 1383 | ; if not solved
|
1363 | 1384 | then do { addInertForAll qci
|
1364 | 1385 | ; stopWith (CtWanted wtd) "Wanted forall-constraint:unsolved" }
|
... | ... | @@ -1379,34 +1400,6 @@ solveWantedForAll qci tvs theta body_pred |
1379 | 1400 | ClassPred cls tys -> pSizeClassPred cls tys
|
1380 | 1401 | _ -> pSizeType pred
|
1381 | 1402 | |
1382 | -trySolveImplication :: Implication -> TcS Bool
|
|
1383 | -trySolveImplication imp
|
|
1384 | - = tryTcS $
|
|
1385 | - do { imp' <- solveImplication imp
|
|
1386 | - ; return (emptyWC { wc_impl = unitBag imp' }) }
|
|
1387 | - -- ToDo: this emptyWC bit is somewhat clumsy
|
|
1388 | - |
|
1389 | -{-
|
|
1390 | -solveWantedForAll_spec :: WantedCtEvidence -> TcS (StopOrContinue Void)
|
|
1391 | --- Solve this implication constraint completely or not at all
|
|
1392 | -solveWantedForAll_spec wtd
|
|
1393 | - = do { traceTcS "solveWantedForAll {" (ppr wtd)
|
|
1394 | - ; fully_solved <- tryTcS (setTcSMode TcSVanilla $
|
|
1395 | - solveWanteds (mkSimpleWC [ev]))
|
|
1396 | - -- It's crucial to call solveWanteds here, not solveSimpleWanteds,
|
|
1397 | - -- because solving `ev` will land in solveWantedForAll_norm,
|
|
1398 | - -- which emits an implication, which we must then solve
|
|
1399 | - ; if fully_solved
|
|
1400 | - then do { traceTcS "solveWantedForAll: fully solved }" (ppr wtd)
|
|
1401 | - ; return $ Stop ev (text "Fully solved:" <+> ppr wtd) }
|
|
1402 | - else do { traceTcS "solveWantedForAll: not fully solved }" (ppr wtd)
|
|
1403 | - ; updInertIrreds (IrredCt ev IrredShapeReason)
|
|
1404 | - -- Stash the unsolved quantified constraint in the irreds
|
|
1405 | - ; return $ Stop ev (text "Not fully solved:" <+> ppr wtd) } }
|
|
1406 | - where
|
|
1407 | - ev = CtWanted wtd
|
|
1408 | --}
|
|
1409 | - |
|
1410 | 1403 | {- Note [Solving a Wanted forall-constraint]
|
1411 | 1404 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1412 | 1405 | Solving a wanted forall (quantified) constraint
|
... | ... | @@ -894,7 +894,7 @@ evVarsOfTypeable ev = |
894 | 894 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
895 | 895 | Finding the free vars of an EvFun is made tricky by the fact the
|
896 | 896 | bindings et_binds may be a mutable variable. Fortunately, we
|
897 | -can just squeeze by. Here's how.
|
|
897 | +ocan just squeeze by. Here's how.
|
|
898 | 898 | |
899 | 899 | * evVarsOfTerm is used only by GHC.Tc.Solver.neededEvVars.
|
900 | 900 | * Each EvBindsVar in an et_binds field of an EvFun is /also/ in the
|