Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
GHC
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
4,251
Issues
4,251
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
396
Merge Requests
396
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Glasgow Haskell Compiler
GHC
Commits
5802ebdd
Commit
5802ebdd
authored
Apr 02, 2012
by
dimitris
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Dropping the idempotence restriction on the inert substitution,
for efficiency. More documentation to follow.
parent
8580b976
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
24 additions
and
69 deletions
+24
-69
compiler/typecheck/TcInteract.lhs
compiler/typecheck/TcInteract.lhs
+24
-69
No files found.
compiler/typecheck/TcInteract.lhs
View file @
5802ebdd
...
...
@@ -55,7 +55,7 @@ import qualified Data.Traversable as Traversable
import Data.Maybe ( isJust )
import Control.Monad( when, unless )
import Pair (
pSnd
)
import Pair ()
import UniqFM
import FastString ( sLit )
import DynFlags
...
...
@@ -316,9 +316,10 @@ kickOutRewritableInerts ct
rewriteInertEqsFromInertEq :: (TcTyVar, TcCoercion, CtFlavor) -- A new substitution
-> TyVarEnv Ct -- All the inert equalities
-> TcS (TyVarEnv Ct) -- The new inert equalities
rewriteInertEqsFromInertEq (subst_tv, subst_co, subst_fl) ieqs
-- The goal: traverse the inert equalities and rewrite some of them, dropping some others
-- back to the worklist. This is delicate, see Note [Delicate equality kick-out]
rewriteInertEqsFromInertEq (subst_tv, _subst_co, subst_fl) ieqs
-- The goal: traverse the inert equalities and throw some of them back to the worklist
-- if you have to rewrite and recheck them for occurs check errors.
-- This is delicate, see Note [Delicate equality kick-out]
= do { mieqs <- Traversable.mapM do_one ieqs
; traceTcS "Original inert equalities:" (ppr ieqs)
; let flatten_justs elem venv
...
...
@@ -330,63 +331,18 @@ rewriteInertEqsFromInertEq (subst_tv, subst_co, subst_fl) ieqs
where do_one ct
| subst_fl `canRewrite` fl && (subst_tv `elemVarSet` tyVarsOfCt ct)
-- Annoyingly inefficient, but we can't simply check
-- that isReflCo co because of cached solved ReflCo evidence.
= if fl `canRewrite` subst_fl then
-- If also the inert can rewrite the subst it's totally safe
-- to rewrite on the spot
do {
{- DV: I thought this might work but not because you don't have the full knowledge of the
implications (just the worklist). And it's a bit tedious. SPJ and I discussed about breaking
the 'idempotent substitution' invariant to be a little more lazy. -}
-- DV: Very experimental!
-- If it's a given equality and its LHS does not appear in the worklist
-- there is no point in rewriting him. In fact there is not point in keeping him,
-- at all, is there?
worklist_tvs <- getTcSWorkListTvs
; if isGiven (cc_flavor ct) && not (tyVarsOfCt ct `elemVarSet` worklist_tvs) then
return Nothing
else do {
ct' <- rewrite_on_the_spot ct
; return $ Just ct' }
}
-- If also the inert can rewrite the subst then there is no danger of
-- occurs check errors sor keep it there. No need to rewrite the inert equality
-- (as we did in the past): See Note [Non-idempotent inert substitution]
return (Just ct)
-- used to be: rewrite_on_the_spot ct >>= ( return . Just )
else -- We have to throw inert back to worklist for occurs checks
do { updWorkListTcS (extendWorkListEq ct)
; return Nothing }
updWorkListTcS (extendWorkListEq ct) >> return Nothing
| otherwise -- Just keep it there
= return
$ Just ct
= return
(Just ct)
where
-- We have that: subst_co :: subst_tv ~ tau
-- An an old inert: tv ~ rhs
-- That we want to rewrite on-the-spot to tv ~ rhs[tau/subst_tv]
fl = cc_flavor ct
tv = cc_tyvar ct
rhs = cc_rhs ct
rewrite_on_the_spot ct
= do { let rhs_co = liftTcCoSubstWith [subst_tv] [subst_co] rhs
eq_co = mkTcTyConAppCo eqTyCon $
[ mkTcReflCo (defaultKind $ typeKind rhs)
, mkTcReflCo (mkTyVarTy tv)
, mkTcSymCo rhs_co ]
new_rhs = pSnd (tcCoercionKind rhs_co)
new_eq_pred = mkTcEqPred (mkTyVarTy tv) new_rhs
-- eq_co :: (tv ~ rhs[s/x]) ~ (tv ~ rhs[x])
; mb_fl <- rewriteCtFlavor fl new_eq_pred eq_co
; case mb_fl of
Just new_fl -> return $
ct {cc_flavor=new_fl,cc_rhs=new_rhs}
Nothing -> -- Weird, rewritten constraint was solved
-- before -- I am uncertain about what to do
pprPanic "Interesting: \
rewrote inert equality to existing!" $
vcat [ text "original ="<+>ppr ct
, text "new eqpred ="<+>ppr new_eq_pred ]
}
kick_out_rewritable :: Ct
-> InertSet
...
...
@@ -451,25 +407,24 @@ Note [Delicate equality kick-out]
Delicate:
When kicking out rewritable constraints, it would be safe to simply
kick out all rewritable equalities, but instead we only kick out those
that, when rewritten, may result in occur-check errors. We rewrite the
rest on the spot. Example:
that, when rewritten, may result in occur-check errors. Example:
WorkItem = [
S
] a ~ b
WorkItem = [
G
] a ~ b
Inerts = { [W] b ~ [a] }
Now at this point the work item cannot be further rewritten by the
inert (due to the weaker inert flavor), so we are examining if we can
instead rewrite the inert from the workitem. But if we rewrite it on
the spot we have to recanonicalize because of the danger of occurs
errors. On the other hand if the inert flavor was just as powerful or
more powerful than the workitem flavor, the work-item could not have
reached this stage (because it would have already been rewritten by
the inert).
inert (due to the weaker inert flavor). Instead the workitem can
rewrite the inert leading to potential occur check errors. So we must
kick the inert out. On the other hand, if the inert flavor was as
powerful or more powerful than the workitem flavor, the work-item could
not have reached this stage (because it would have already been
rewritten by the inert).
The coclusion is: we kick out the 'dangerous' equalities that may
require recanonicalization (occurs checks) and the rest we rewrite
unconditionally without further checks, on-the-spot with function
rewriteInertEqsFromInertEq.
require recanonicalization (occurs checks) and the rest we keep
there in the inerts without further checks.
In the past we used to rewrite-on-the-spot those equalities that we keep in,
but this is no longer necessary see Note [Non-idempotent inert substitution].
\begin{code}
data SPSolveResult = SPCantSolve
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment