Simon Peyton Jones pushed to branch wip/T26115 at Glasgow Haskell Compiler / GHC
Commits:
-
024c8349
by Simon Peyton Jones at 2025-06-15T23:43:40+01:00
-
4bf402c6
by Simon Peyton Jones at 2025-06-15T23:43:54+01:00
-
1d2f05d1
by Simon Peyton Jones at 2025-06-15T23:44:06+01:00
-
d82e2219
by Simon Peyton Jones at 2025-06-15T23:44:28+01:00
-
13a1fcec
by Simon Peyton Jones at 2025-06-15T23:46:58+01:00
5 changed files:
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/Type.hs
Changes:
... | ... | @@ -1784,43 +1784,6 @@ alreadyCovered env bndrs fn args is_active rules |
1784 | 1784 | where
|
1785 | 1785 | in_scope = substInScopeSet (se_subst env)
|
1786 | 1786 | |
1787 | -{-
|
|
1788 | -specRhs :: SpecEnv -> [InVar] -> InExpr -> [OutExpr]
|
|
1789 | - -> SpecM (OutExpr, UsageDetails)
|
|
1790 | - |
|
1791 | -specRhs env bndrs body [] -- Like specExpr (Lam bndrs body)
|
|
1792 | - = specLam env' bndrs' body
|
|
1793 | - where
|
|
1794 | - (env', bndrs') = substBndrs env bndrs
|
|
1795 | - |
|
1796 | -specRhs _env [] body args
|
|
1797 | - = -- The caller should have ensured that there are no more
|
|
1798 | - -- args than we have binders on the RHS
|
|
1799 | - pprPanic "specRhs:too many args" (ppr args $$ ppr body)
|
|
1800 | - |
|
1801 | -specRhs env@(SE { se_subst = subst }) (bndr:bndrs) body (arg:args)
|
|
1802 | - | exprIsTrivial arg
|
|
1803 | - , let env' = env { se_subst = Core.extendSubst subst bndr arg }
|
|
1804 | - = specRhs env' bndrs body args
|
|
1805 | - |
|
1806 | - |
|
1807 | - | otherwise -- Non-trivial argument; it must be a dictionary
|
|
1808 | - = do { fresh_id <- newIdBndr "dx" (exprType arg)
|
|
1809 | - ; let fresh_id' = fresh_id `addDictUnfolding` arg
|
|
1810 | - dict_bind = mkDB (NonRec fresh_id' arg)
|
|
1811 | - env' = env { se_subst = Core.extendSubst subst bndr (Var fresh_id')
|
|
1812 | - `Core.extendSubstInScope` fresh_id' }
|
|
1813 | - -- Ensure the new unfolding is in the in-scope set
|
|
1814 | - ; (body', uds) <- specRhs env' bndrs body args
|
|
1815 | - ; return (body', dict_bind `consDictBind` uds) }
|
|
1816 | - |
|
1817 | -consDictBind :: DictBind -> UsageDetails -> UsageDetails
|
|
1818 | -consDictBind db uds@MkUD{ud_binds=FDB{fdb_binds = binds, fdb_bndrs = bs}}
|
|
1819 | - = uds { ud_binds = FDB{ fdb_binds = db `consOL` binds
|
|
1820 | - , fdb_bndrs = bs `extendVarSetList` bindersOfDictBind db } }
|
|
1821 | - |
|
1822 | --}
|
|
1823 | - |
|
1824 | 1787 | -- Convenience function for invoking lookupRule from Specialise
|
1825 | 1788 | -- The SpecEnv's InScopeSet should include all the Vars in the [CoreExpr]
|
1826 | 1789 | specLookupRule :: HasDebugCallStack
|
... | ... | @@ -2611,7 +2574,7 @@ specHeader subst (bndr:bndrs) (UnspecType : args) |
2611 | 2574 | |
2612 | 2575 | specHeader subst (bndr:bndrs) (_ : args)
|
2613 | 2576 | | isDeadBinder bndr
|
2614 | - , let (subst1, bndr') = Core.substBndr subst bndr
|
|
2577 | + , let (subst1, bndr') = Core.substBndr subst (zapIdOccInfo bndr)
|
|
2615 | 2578 | , Just rubbish_lit <- mkLitRubbish (idType bndr')
|
2616 | 2579 | = -- See Note [Drop dead args from specialisations]
|
2617 | 2580 | do { (useful, subst2, rule_bs, rule_es, spec_bs, spec_args) <- specHeader subst1 bndrs args
|
... | ... | @@ -1100,6 +1100,7 @@ dsSpec_help poly_nm poly_id poly_rhs inl bndrs ds_call |
1100 | 1100 | |
1101 | 1101 | ; tracePm "dsSpec(new route)" $
|
1102 | 1102 | vcat [ text "poly_id" <+> ppr poly_id
|
1103 | + , text "unfolding" <+> ppr (realIdUnfolding poly_id)
|
|
1103 | 1104 | , text "bndrs" <+> ppr bndrs
|
1104 | 1105 | , text "ds_call" <+> ppr ds_call
|
1105 | 1106 | , text "core_call" <+> ppr core_call
|
... | ... | @@ -1274,17 +1274,19 @@ solveForAllNC ev tvs theta body_pred |
1274 | 1274 | -- Precondition: the constraint has already been rewritten by the inert set.
|
1275 | 1275 | solveForAll :: CtEvidence -> [TcTyVar] -> TcThetaType -> PredType -> ExpansionFuel
|
1276 | 1276 | -> TcS (StopOrContinue Void)
|
1277 | -solveForAll ev tvs theta body_pred fuel =
|
|
1278 | - case ev of
|
|
1279 | - CtGiven {} ->
|
|
1280 | - -- See Note [Solving a Given forall-constraint]
|
|
1281 | - do { addInertForAll qci
|
|
1282 | - ; stopWith ev "Given forall-constraint" }
|
|
1283 | - CtWanted wtd ->
|
|
1284 | - -- See Note [Solving a Wanted forall-constraint]
|
|
1285 | - runSolverStage $
|
|
1286 | - do { tryInertQCs qci
|
|
1287 | - ; Stage $ solveWantedForAll wtd tvs theta body_pred }
|
|
1277 | +solveForAll ev tvs theta body_pred fuel
|
|
1278 | + = case ev of
|
|
1279 | + CtGiven {} ->
|
|
1280 | + -- See Note [Solving a Given forall-constraint]
|
|
1281 | + do { addInertForAll qci
|
|
1282 | + ; stopWith ev "Given forall-constraint" }
|
|
1283 | + CtWanted wtd ->
|
|
1284 | + do { mode <- getTcSMode
|
|
1285 | + ; case mode of -- See Note [TcSSpecPrag] in GHC.Tc.Solver.Monad.
|
|
1286 | + TcSSpecPrag -> solveWantedForAll_spec wtd
|
|
1287 | + _ -> runSolverStage $
|
|
1288 | + do { tryInertQCs qci
|
|
1289 | + ; solveWantedForAll_norm wtd tvs theta body_pred } }
|
|
1288 | 1290 | where
|
1289 | 1291 | qci = QCI { qci_ev = ev, qci_tvs = tvs
|
1290 | 1292 | , qci_body = body_pred, qci_pend_sc = fuel }
|
... | ... | @@ -1312,82 +1314,78 @@ try_inert_qcs (QCI { qci_ev = ev_w }) inerts = |
1312 | 1314 | = Nothing
|
1313 | 1315 | |
1314 | 1316 | -- | Solve a (canonical) Wanted quantified constraint by emitting an implication.
|
1315 | ---
|
|
1316 | 1317 | -- See Note [Solving a Wanted forall-constraint]
|
1317 | -solveWantedForAll :: WantedCtEvidence -> [TcTyVar] -> TcThetaType -> PredType
|
|
1318 | - -> TcS (StopOrContinue Void)
|
|
1319 | -solveWantedForAll wtd@(WantedCt { ctev_dest = dest, ctev_loc = loc
|
|
1320 | - , ctev_rewriters = rewriters })
|
|
1318 | +solveWantedForAll_norm :: WantedCtEvidence -> [TcTyVar] -> TcThetaType -> PredType
|
|
1319 | + -> SolverStage Void
|
|
1320 | +solveWantedForAll_norm wtd@(WantedCt { ctev_dest = dest, ctev_loc = loc
|
|
1321 | + , ctev_rewriters = rewriters })
|
|
1321 | 1322 | tvs theta body_pred
|
1322 | - = -- We are about to do something irreversible (turning a quantified constraint
|
|
1323 | - -- into an implication), so wrap the inner call in solveCompletelyIfRequired
|
|
1324 | - -- to ensure we can roll back if we can't solve the implication fully.
|
|
1325 | - -- See Note [TcSSpecPrag] in GHC.Tc.Solver.Monad.
|
|
1326 | - do { mode <- getTcSMode
|
|
1327 | - ; case mode of
|
|
1328 | - TcSSpecPrag
|
|
1329 | - -> do { traceTcS "solveWantedForAll {" (ppr wtd)
|
|
1330 | - ; fully_solved <- tryTcS (setTcSMode TcSVanilla $
|
|
1331 | - solveSimpleWanteds (unitBag ct))
|
|
1332 | - ; if fully_solved
|
|
1333 | - then do { traceTcS "solveWantedForAll: fully solved }" (ppr wtd)
|
|
1334 | - ; return $ Stop ev (text "Fully solved:" <+> ppr wtd) }
|
|
1335 | - else do { traceTcS "solveWantedForAll: fully solved }" (ppr wtd)
|
|
1336 | - ; updInertIrreds (IrredCt ev IrredShapeReason)
|
|
1337 | - -- Stash the unsolved quantified constraint in the irreds
|
|
1338 | - ; return $ Stop ev (text "Not fully solved:" <+> ppr wtd) } }
|
|
1339 | - |
|
1340 | - _ -> do { solve_by_emitting_implic
|
|
1341 | - ; stopWith ev "Wanted forall-constraint (implication)" } }
|
|
1323 | + = Stage $
|
|
1324 | + TcS.setSrcSpan (getCtLocEnvLoc $ ctLocEnv loc) $
|
|
1325 | + -- This setSrcSpan is important: the emitImplicationTcS uses that
|
|
1326 | + -- TcLclEnv for the implication, and that in turn sets the location
|
|
1327 | + -- for the Givens when solving the constraint (#21006)
|
|
1328 | + |
|
1329 | + do { -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
|
|
1330 | + -- in GHC.Tc.Utils.TcType
|
|
1331 | + -- Very like the code in tcSkolDFunType
|
|
1332 | + rec { skol_info <- mkSkolemInfo skol_info_anon
|
|
1333 | + ; (subst, skol_tvs) <- tcInstSkolTyVarsX skol_info empty_subst tvs
|
|
1334 | + ; let inst_pred = substTy subst body_pred
|
|
1335 | + inst_theta = substTheta subst theta
|
|
1336 | + skol_info_anon = InstSkol is_qc (get_size inst_pred) }
|
|
1337 | + |
|
1338 | + ; given_ev_vars <- mapM newEvVar inst_theta
|
|
1339 | + ; (lvl, (w_id, wanteds))
|
|
1340 | + <- pushLevelNoWorkList (ppr skol_info) $
|
|
1341 | + do { let loc' = setCtLocOrigin loc (ScOrigin is_qc NakedSc)
|
|
1342 | + -- Set the thing to prove to have a ScOrigin, so we are
|
|
1343 | + -- careful about its termination checks.
|
|
1344 | + -- See (QC-INV) in Note [Solving a Wanted forall-constraint]
|
|
1345 | + ; wanted_ev <- newWantedNC loc' rewriters inst_pred
|
|
1346 | + -- NB: inst_pred can be an equality
|
|
1347 | + ; return ( wantedCtEvEvId wanted_ev
|
|
1348 | + , unitBag (mkNonCanonical $ CtWanted wanted_ev)) }
|
|
1349 | + |
|
1350 | + ; traceTcS "solveForAll" (ppr given_ev_vars $$ ppr wanteds $$ ppr w_id)
|
|
1351 | + ; ev_binds <- emitImplicationTcS lvl skol_info_anon skol_tvs given_ev_vars wanteds
|
|
1342 | 1352 | |
1353 | + ; setWantedEvTerm dest EvCanonical $
|
|
1354 | + EvFun { et_tvs = skol_tvs, et_given = given_ev_vars
|
|
1355 | + , et_binds = ev_binds, et_body = w_id }
|
|
1356 | + ; stopWith (CtWanted wtd) "Wanted forall-constraint (implication)" }
|
|
1343 | 1357 | where
|
1344 | - ev = CtWanted wtd
|
|
1345 | - ct = mkNonCanonical ev
|
|
1346 | 1358 | is_qc = IsQC (ctLocOrigin loc)
|
1347 | 1359 | |
1348 | 1360 | empty_subst = mkEmptySubst $ mkInScopeSet $
|
1349 | 1361 | tyCoVarsOfTypes (body_pred:theta) `delVarSetList` tvs
|
1350 | 1362 | |
1351 | - -- This setSrcSpan is important: the emitImplicationTcS uses that
|
|
1352 | - -- TcLclEnv for the implication, and that in turn sets the location
|
|
1353 | - -- for the Givens when solving the constraint (#21006)
|
|
1354 | - solve_by_emitting_implic
|
|
1355 | - = TcS.setSrcSpan (getCtLocEnvLoc $ ctLocEnv loc) $
|
|
1356 | - do { -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]
|
|
1357 | - -- in GHC.Tc.Utils.TcType
|
|
1358 | - -- Very like the code in tcSkolDFunType
|
|
1359 | - rec { skol_info <- mkSkolemInfo skol_info_anon
|
|
1360 | - ; (subst, skol_tvs) <- tcInstSkolTyVarsX skol_info empty_subst tvs
|
|
1361 | - ; let inst_pred = substTy subst body_pred
|
|
1362 | - inst_theta = substTheta subst theta
|
|
1363 | - skol_info_anon = InstSkol is_qc (get_size inst_pred) }
|
|
1364 | - |
|
1365 | - ; given_ev_vars <- mapM newEvVar inst_theta
|
|
1366 | - ; (lvl, (w_id, wanteds))
|
|
1367 | - <- pushLevelNoWorkList (ppr skol_info) $
|
|
1368 | - do { let loc' = setCtLocOrigin loc (ScOrigin is_qc NakedSc)
|
|
1369 | - -- Set the thing to prove to have a ScOrigin, so we are
|
|
1370 | - -- careful about its termination checks.
|
|
1371 | - -- See (QC-INV) in Note [Solving a Wanted forall-constraint]
|
|
1372 | - ; wanted_ev <- newWantedNC loc' rewriters inst_pred
|
|
1373 | - -- NB: inst_pred can be an equality
|
|
1374 | - ; return ( wantedCtEvEvId wanted_ev
|
|
1375 | - , unitBag (mkNonCanonical $ CtWanted wanted_ev)) }
|
|
1376 | - |
|
1377 | - ; traceTcS "solveForAll" (ppr given_ev_vars $$ ppr wanteds $$ ppr w_id)
|
|
1378 | - ; ev_binds <- emitImplicationTcS lvl skol_info_anon skol_tvs given_ev_vars wanteds
|
|
1379 | - |
|
1380 | - ; setWantedEvTerm dest EvCanonical $
|
|
1381 | - EvFun { et_tvs = skol_tvs, et_given = given_ev_vars
|
|
1382 | - , et_binds = ev_binds, et_body = w_id }
|
|
1383 | - }
|
|
1384 | - |
|
1385 | 1363 | -- Getting the size of the head is a bit horrible
|
1386 | 1364 | -- because of the special treament for class predicates
|
1387 | 1365 | get_size pred = case classifyPredType pred of
|
1388 | 1366 | ClassPred cls tys -> pSizeClassPred cls tys
|
1389 | 1367 | _ -> pSizeType pred
|
1390 | 1368 | |
1369 | +solveWantedForAll_spec :: WantedCtEvidence -> TcS (StopOrContinue Void)
|
|
1370 | +-- Solve this implication constraint completely or not at all
|
|
1371 | +solveWantedForAll_spec wtd
|
|
1372 | + = do { traceTcS "solveWantedForAll {" (ppr wtd)
|
|
1373 | + ; fully_solved <- tryTcS (setTcSMode TcSVanilla $
|
|
1374 | + solveWanteds (mkSimpleWC [ev]))
|
|
1375 | + -- It's crucial to call solveWanteds here, not solveSimpleWanteds,
|
|
1376 | + -- because solving `ev` will land in solveWantedForAll_norm,
|
|
1377 | + -- which emits an implication, which we must then solve
|
|
1378 | + ; if fully_solved
|
|
1379 | + then do { traceTcS "solveWantedForAll: fully solved }" (ppr wtd)
|
|
1380 | + ; return $ Stop ev (text "Fully solved:" <+> ppr wtd) }
|
|
1381 | + else do { traceTcS "solveWantedForAll: not fully solved }" (ppr wtd)
|
|
1382 | + ; updInertIrreds (IrredCt ev IrredShapeReason)
|
|
1383 | + -- Stash the unsolved quantified constraint in the irreds
|
|
1384 | + ; return $ Stop ev (text "Not fully solved:" <+> ppr wtd) } }
|
|
1385 | + where
|
|
1386 | + ev = CtWanted wtd
|
|
1387 | + |
|
1388 | + |
|
1391 | 1389 | {- Note [Solving a Wanted forall-constraint]
|
1392 | 1390 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
1393 | 1391 | Solving a wanted forall (quantified) constraint
|
... | ... | @@ -581,6 +581,11 @@ implicationNeeded skol_info skol_tvs given |
581 | 581 | |
582 | 582 | alwaysBuildImplication :: SkolemInfoAnon -> Bool
|
583 | 583 | -- See Note [When to build an implication]
|
584 | +alwaysBuildImplication (SigSkol ctxt _ _)
|
|
585 | + = case ctxt of
|
|
586 | + FunSigCtxt {} -> True -- RHS of a binding with a signature
|
|
587 | + SpecInstCtxt -> True -- SpecInstCtxt: this is rather delicate
|
|
588 | + _ -> False
|
|
584 | 589 | alwaysBuildImplication _ = False
|
585 | 590 | |
586 | 591 | {- Commmented out for now while I figure out about error messages.
|
... | ... | @@ -746,8 +746,12 @@ zonk_bind (XHsBindsLR (AbsBinds { abs_tvs = tyvars, abs_ev_vars = evs |
746 | 746 | runZonkBndrT (zonkTyBndrsX tyvars ) $ \ new_tyvars ->
|
747 | 747 | runZonkBndrT (zonkEvBndrsX evs ) $ \ new_evs ->
|
748 | 748 | runZonkBndrT (zonkTcEvBinds_s ev_binds) $ \ new_ev_binds ->
|
749 | - do { (new_val_bind, new_exports) <- mfix $ \ ~(new_val_binds, _) ->
|
|
750 | - runZonkBndrT (extendIdZonkEnvRec $ collectHsBindsBinders CollNoDictBinders new_val_binds) $ \ _ ->
|
|
749 | + do { (new_val_bind, new_exports) <- mfix $ \ ~(new_val_binds, new_exports) ->
|
|
750 | + let new_bndrs = collectHsBindsBinders CollNoDictBinders new_val_binds
|
|
751 | + ++ map abe_poly new_exports
|
|
752 | + -- Tie the knot with the `abe_poly` binders too, since they
|
|
753 | + -- may be mentioned in the `abe_prags` of the `exports`
|
|
754 | + in runZonkBndrT (extendIdZonkEnvRec new_bndrs) $ \ _ ->
|
|
751 | 755 | do { new_val_binds <- mapM zonk_val_bind val_binds
|
752 | 756 | ; new_exports <- mapM zonk_export exports
|
753 | 757 | ; return (new_val_binds, new_exports)
|
... | ... | @@ -854,6 +858,7 @@ zonkLTcSpecPrags ps |
854 | 858 | ; skol_tvs_ref <- lift $ newTcRef []
|
855 | 859 | ; setZonkType (SkolemiseFlexi skol_tvs_ref) $
|
856 | 860 | -- SkolemiseFlexi: see Note [Free tyvars on rule LHS]
|
861 | + |
|
857 | 862 | runZonkBndrT (zonkCoreBndrsX bndrs) $ \ bndrs' ->
|
858 | 863 | do { spec_e' <- zonkLExpr spec_e
|
859 | 864 | ; skol_tvs <- lift $ readTcRef skol_tvs_ref
|