summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2012-05-15 18:18:19 +0100
committerIan Lynagh <igloo@earth.li>2012-05-15 18:18:19 +0100
commit5ccb43f3306bb0907948d97ea6bffe9f70c69554 (patch)
tree3cb6caaa3c6f2d5a0a1057d939514010ed492416
parent59e1f0687aa6e2d65c4de314f80b13e4aedad8bc (diff)
parent921530b477867edb5158e4ad5bbbdb5c7c531c97 (diff)
downloadhaskell-5ccb43f3306bb0907948d97ea6bffe9f70c69554.tar.gz
Merge branch 'master' of http://darcs.haskell.org//ghc
-rw-r--r--aclocal.m42
-rw-r--r--bindisttest/Makefile4
-rw-r--r--bindisttest/ghc.mk4
-rw-r--r--compiler/coreSyn/CoreSyn.lhs12
-rw-r--r--compiler/coreSyn/CoreUnfold.lhs180
-rw-r--r--compiler/coreSyn/CoreUtils.lhs74
-rw-r--r--compiler/coreSyn/PprCore.lhs4
-rw-r--r--compiler/deSugar/DsBinds.lhs110
-rw-r--r--compiler/deSugar/DsMeta.hs43
-rw-r--r--compiler/ghci/ByteCodeGen.lhs3
-rw-r--r--compiler/hsSyn/Convert.lhs22
-rw-r--r--compiler/hsSyn/HsDecls.lhs32
-rw-r--r--compiler/hsSyn/HsPat.lhs4
-rw-r--r--compiler/hsSyn/HsTypes.lhs126
-rw-r--r--compiler/hsSyn/HsUtils.lhs5
-rw-r--r--compiler/main/DynFlags.hs44
-rw-r--r--compiler/main/HscMain.hs8
-rw-r--r--compiler/main/HscTypes.lhs4
-rw-r--r--compiler/main/InteractiveEval.hs17
-rw-r--r--compiler/main/Packages.lhs75
-rw-r--r--compiler/parser/Lexer.x21
-rw-r--r--compiler/parser/Parser.y.pp8
-rw-r--r--compiler/parser/ParserCore.y10
-rw-r--r--compiler/parser/RdrHsSyn.lhs25
-rw-r--r--compiler/rename/RnBinds.lhs2
-rw-r--r--compiler/rename/RnEnv.lhs17
-rw-r--r--compiler/rename/RnPat.lhs4
-rw-r--r--compiler/rename/RnSource.lhs81
-rw-r--r--compiler/rename/RnTypes.lhs264
-rw-r--r--compiler/simplCore/SimplUtils.lhs130
-rw-r--r--compiler/simplCore/Simplify.lhs85
-rw-r--r--compiler/typecheck/Inst.lhs72
-rw-r--r--compiler/typecheck/TcBinds.lhs59
-rw-r--r--compiler/typecheck/TcCanonical.lhs252
-rw-r--r--compiler/typecheck/TcErrors.lhs48
-rw-r--r--compiler/typecheck/TcEvidence.lhs103
-rw-r--r--compiler/typecheck/TcHsSyn.lhs29
-rw-r--r--compiler/typecheck/TcHsType.lhs41
-rw-r--r--compiler/typecheck/TcInstDcls.lhs4
-rw-r--r--compiler/typecheck/TcInteract.lhs369
-rw-r--r--compiler/typecheck/TcMType.lhs29
-rw-r--r--compiler/typecheck/TcRnDriver.lhs38
-rw-r--r--compiler/typecheck/TcRnTypes.lhs173
-rw-r--r--compiler/typecheck/TcSMonad.lhs668
-rw-r--r--compiler/typecheck/TcSimplify.lhs50
-rw-r--r--compiler/typecheck/TcTyClsDecls.lhs31
-rw-r--r--compiler/typecheck/TcUnify.lhs4
-rw-r--r--compiler/types/Coercion.lhs14
-rw-r--r--compiler/types/FunDeps.lhs4
-rw-r--r--compiler/types/TyCon.lhs6
-rw-r--r--compiler/types/Type.lhs17
-rw-r--r--compiler/types/Unify.lhs50
-rw-r--r--configure.ac4
-rw-r--r--docs/users_guide/flags.xml32
-rw-r--r--docs/users_guide/packages.xml108
-rw-r--r--docs/users_guide/runghc.xml2
-rw-r--r--ghc.mk2
-rw-r--r--ghc/InteractiveUI.hs2
-rw-r--r--libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs4
-rw-r--r--mk/config.mk.in2
-rw-r--r--rules/distdir-way-opts.mk2
-rw-r--r--rules/package-config.mk8
-rw-r--r--utils/ghc-cabal/Main.hs2
-rw-r--r--utils/ghc-cabal/ghc.mk2
-rw-r--r--utils/ghc-pkg/Main.hs20
-rw-r--r--utils/ghc-pkg/ghc-pkg.wrapper2
-rw-r--r--utils/ghc-pkg/ghc.mk6
67 files changed, 2020 insertions, 1659 deletions
diff --git a/aclocal.m4 b/aclocal.m4
index c196bdf026..f05dfe96ea 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1808,7 +1808,7 @@ AC_MSG_NOTICE(Building in-tree ghc-pwd)
dnl except we don't want to have to know what make is called. Sigh.
rm -rf utils/ghc-pwd/dist-boot
mkdir utils/ghc-pwd/dist-boot
- if ! "$WithGhc" -v0 -no-user-package-conf -hidir utils/ghc-pwd/dist-boot -odir utils/ghc-pwd/dist-boot -stubdir utils/ghc-pwd/dist-boot --make utils/ghc-pwd/Main.hs -o utils/ghc-pwd/dist-boot/ghc-pwd
+ if ! "$WithGhc" -v0 -no-user-$GHC_PACKAGE_DB_FLAG -hidir utils/ghc-pwd/dist-boot -odir utils/ghc-pwd/dist-boot -stubdir utils/ghc-pwd/dist-boot --make utils/ghc-pwd/Main.hs -o utils/ghc-pwd/dist-boot/ghc-pwd
then
AC_MSG_ERROR([Building ghc-pwd failed])
fi
diff --git a/bindisttest/Makefile b/bindisttest/Makefile
index 238bce7650..7d20bdbf39 100644
--- a/bindisttest/Makefile
+++ b/bindisttest/Makefile
@@ -48,8 +48,8 @@ endif
$(BIN_DIST_INST_DIR)/bin/ghc --make HelloWorld
./HelloWorld > output
$(CONTEXT_DIFF) output expected_output
-# Without --no-user-package-conf we might pick up random packages from ~/.ghc
- $(BIN_DIST_INST_DIR)/bin/ghc-pkg check --no-user-package-conf
+# Without --no-user-package-db we might pick up random packages from ~/.ghc
+ $(BIN_DIST_INST_DIR)/bin/ghc-pkg check --no-user-package-db
clean distclean:
"$(RM)" $(RM_OPTS_REC) $(BIN_DIST_INST_SUBDIR)
diff --git a/bindisttest/ghc.mk b/bindisttest/ghc.mk
index e051be0ccd..c911da5e8c 100644
--- a/bindisttest/ghc.mk
+++ b/bindisttest/ghc.mk
@@ -48,8 +48,8 @@ endif
$(BIN_DIST_INST_DIR)/bin/ghc --make bindisttest/HelloWorld
bindisttest/HelloWorld > bindisttest/output
$(CONTEXT_DIFF) bindisttest/output bindisttest/expected_output
-# Without --no-user-package-conf we might pick up random packages from ~/.ghc
- $(BIN_DIST_INST_DIR)/bin/ghc-pkg check --no-user-package-conf
+# Without --no-user-package-db we might pick up random packages from ~/.ghc
+ $(BIN_DIST_INST_DIR)/bin/ghc-pkg check --no-user-package-db
$(eval $(call clean-target,bindisttest,all,$(BIN_DIST_INST_DIR) $(wildcard bindisttest/a/b/c/*) bindisttest/HelloWorld bindisttest/HelloWorld.o bindisttest/HelloWorld.hi bindisttest/output))
diff --git a/compiler/coreSyn/CoreSyn.lhs b/compiler/coreSyn/CoreSyn.lhs
index 29fe407e50..bfe6dec72e 100644
--- a/compiler/coreSyn/CoreSyn.lhs
+++ b/compiler/coreSyn/CoreSyn.lhs
@@ -649,7 +649,7 @@ data Unfolding
-- a `seq` on this variable
uf_is_conlike :: Bool, -- True <=> applicn of constructor or CONLIKE function
-- Cached version of exprIsConLike
- uf_is_cheap :: Bool, -- True <=> doesn't waste (much) work to expand
+ uf_is_work_free :: Bool, -- True <=> doesn't waste (much) work to expand
-- inside an inlining
-- Cached version of exprIsCheap
uf_expandable :: Bool, -- True <=> can expand in RULE matching
@@ -667,8 +667,8 @@ data Unfolding
-- uf_is_value: 'exprIsHNF' template (cached); it is ok to discard a 'seq' on
-- this variable
--
- -- uf_is_cheap: Does this waste only a little work if we expand it inside an inlining?
- -- Basically this is a cached version of 'exprIsCheap'
+ -- uf_is_work_free: Does this waste only a little work if we expand it inside an inlining?
+ -- Basically this is a cached version of 'exprIsWorkFree'
--
-- uf_guidance: Tells us about the /size/ of the unfolding template
@@ -787,7 +787,7 @@ mkOtherCon = OtherCon
seqUnfolding :: Unfolding -> ()
seqUnfolding (CoreUnfolding { uf_tmpl = e, uf_is_top = top,
- uf_is_value = b1, uf_is_cheap = b2,
+ uf_is_value = b1, uf_is_work_free = b2,
uf_expandable = b3, uf_is_conlike = b4,
uf_arity = a, uf_guidance = g})
= seqExpr e `seq` top `seq` b1 `seq` a `seq` b2 `seq` b3 `seq` b4 `seq` seqGuidance g
@@ -850,8 +850,8 @@ isConLikeUnfolding _ = False
-- | Is the thing we will unfold into certainly cheap?
isCheapUnfolding :: Unfolding -> Bool
-isCheapUnfolding (CoreUnfolding { uf_is_cheap = is_cheap }) = is_cheap
-isCheapUnfolding _ = False
+isCheapUnfolding (CoreUnfolding { uf_is_work_free = is_wf }) = is_wf
+isCheapUnfolding _ = False
isExpandableUnfolding :: Unfolding -> Bool
isExpandableUnfolding (CoreUnfolding { uf_expandable = is_expable }) = is_expable
diff --git a/compiler/coreSyn/CoreUnfold.lhs b/compiler/coreSyn/CoreUnfold.lhs
index 4529dba20d..5817669fe7 100644
--- a/compiler/coreSyn/CoreUnfold.lhs
+++ b/compiler/coreSyn/CoreUnfold.lhs
@@ -145,15 +145,15 @@ mkCoreUnfolding :: UnfoldingSource -> Bool -> CoreExpr
-> Arity -> UnfoldingGuidance -> Unfolding
-- Occurrence-analyses the expression before capturing it
mkCoreUnfolding src top_lvl expr arity guidance
- = CoreUnfolding { uf_tmpl = occurAnalyseExpr expr,
- uf_src = src,
- uf_arity = arity,
- uf_is_top = top_lvl,
- uf_is_value = exprIsHNF expr,
- uf_is_conlike = exprIsConLike expr,
- uf_is_cheap = exprIsCheap expr,
- uf_expandable = exprIsExpandable expr,
- uf_guidance = guidance }
+ = CoreUnfolding { uf_tmpl = occurAnalyseExpr expr,
+ uf_src = src,
+ uf_arity = arity,
+ uf_is_top = top_lvl,
+ uf_is_value = exprIsHNF expr,
+ uf_is_conlike = exprIsConLike expr,
+ uf_is_work_free = exprIsWorkFree expr,
+ uf_expandable = exprIsExpandable expr,
+ uf_guidance = guidance }
mkUnfolding :: UnfoldingSource -> Bool -> Bool -> CoreExpr -> Unfolding
-- Calculates unfolding guidance
@@ -163,17 +163,18 @@ mkUnfolding src top_lvl is_bottoming expr
, not (exprIsTrivial expr)
= NoUnfolding -- See Note [Do not inline top-level bottoming functions]
| otherwise
- = CoreUnfolding { uf_tmpl = occurAnalyseExpr expr,
- uf_src = src,
- uf_arity = arity,
- uf_is_top = top_lvl,
- uf_is_value = exprIsHNF expr,
- uf_is_conlike = exprIsConLike expr,
- uf_expandable = exprIsExpandable expr,
- uf_is_cheap = exprIsCheap expr,
- uf_guidance = guidance }
+ = CoreUnfolding { uf_tmpl = occ_anald_expr,
+ uf_src = src,
+ uf_arity = arity,
+ uf_is_top = top_lvl,
+ uf_is_value = exprIsHNF expr,
+ uf_is_conlike = exprIsConLike expr,
+ uf_expandable = exprIsExpandable expr,
+ uf_is_work_free = exprIsWorkFree expr,
+ uf_guidance = guidance }
where
- (arity, guidance) = calcUnfoldingGuidance expr
+ occ_anald_expr = occurAnalyseExpr expr
+ (arity, guidance) = calcUnfoldingGuidance occ_anald_expr
-- Sometimes during simplification, there's a large let-bound thing
-- which has been substituted, and so is now dead; so 'expr' contains
-- two copies of the thing while the occurrence-analysed expression doesn't
@@ -501,80 +502,6 @@ sizeExpr bOMB_OUT_SIZE top_args expr
d2 -- Ignore d1
\end{code}
-Note [Function application discount]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-I noticed that the output of the supercompiler generates a lot of code
-with this form:
-
-"""
-module Inlining where
-
-h1 k = k undefined undefined undefined
- undefined undefined undefined
- undefined undefined undefined
- undefined undefined undefined
- undefined undefined undefined
- undefined undefined undefined
-
-a = h1 (\x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -> x)
-b = h1 (\_ x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -> x)
-c = h1 (\_ _ x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -> x)
-d = h1 (\_ _ _ x _ _ _ _ _ _ _ _ _ _ _ _ _ _ -> x)
-e = h1 (\_ _ _ _ x _ _ _ _ _ _ _ _ _ _ _ _ _ -> x)
-f = h1 (\_ _ _ _ _ x _ _ _ _ _ _ _ _ _ _ _ _ -> x)
-g = h1 (\_ _ _ _ _ _ x _ _ _ _ _ _ _ _ _ _ _ -> x)
-h = h1 (\_ _ _ _ _ _ _ x _ _ _ _ _ _ _ _ _ _ -> x)
-i = h1 (\_ _ _ _ _ _ _ _ x _ _ _ _ _ _ _ _ _ -> x)
-j = h1 (\_ _ _ _ _ _ _ _ _ x _ _ _ _ _ _ _ _ -> x)
-k = h1 (\_ _ _ _ _ _ _ _ _ _ x _ _ _ _ _ _ _ -> x)
-l = h1 (\_ _ _ _ _ _ _ _ _ _ _ x _ _ _ _ _ _ -> x)
-m = h1 (\_ _ _ _ _ _ _ _ _ _ _ _ x _ _ _ _ _ -> x)
-n = h1 (\_ _ _ _ _ _ _ _ _ _ _ _ _ x _ _ _ _ -> x)
-o = h1 (\_ _ _ _ _ _ _ _ _ _ _ _ _ _ x _ _ _ -> x)
-p = h1 (\_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ x _ _ -> x)
-q = h1 (\_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ x _ -> x)
-r = h1 (\_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ x -> x)
-"""
-
-With GHC head the applications of h1 are not inlined, which hurts the
-quality of the generated code a bit. I was wondering why h1 wasn't
-getting inlined into each of "a" to "i" - after all, it has a manifest
-lambda argument.
-
-It turns out that the code in CoreUnfold gives a fixed discount of
-opt_UF_FunAppDiscount to a function argument such as "k" if it applied
-to any arguments. This is enough to ensure that h1 is inlined if the number
-of arguments applied to k is below a certain limit, but if many arguments are
-applied to k then the fixed discount can't overcome the size of the
-chain of apps, and h1 is never inlined.
-
-My proposed solution is to change CoreUnfold.funSize so that longer
-chains of arguments being applied to a lambda-bound function give a
-bigger discount. The motivation for this is that we would *generally*
-expect that the lambda at the callsite has enough lambdas such that
-all of the applications within the body can be beta-reduced away. This
-change might lead to over eager inlining in cases like this, though:
-
-{{{
-h1 k = k x y z
-
-{-# NOINLINE g #-}
-g = ...
-
-main = ... h1 (\x -> g x) ...
-}}}
-
-In this case we aren't able to beta-reduce away all of the
-applications in the body of h1 because the lambda at the call site
-only binds 1 argument, not the 3 allowed by the type. I don't expect
-this case to be particularly common, however.
-
-I chose the bonus to be (size - 20) so that application to 1 arg got
-same bonus as the old fixed bonus (i.e. opt_UF_FunAppDiscount, which is 60).
-If you have the bonus being (size - 40) then $fMonad[]_$c>>= with interesting
-2nd arg doesn't inline in cryptarithm2 so we lose some deforestation, and
-overall binary size hardly falls.
\begin{code}
-- | Finds a nominal size of a string literal.
@@ -615,23 +542,29 @@ funSize top_args fun n_val_args
where
some_val_args = n_val_args > 0
- -- See Note [Function application discount]
- arg_discount | some_val_args && fun `elem` top_args
- = unitBag (fun, opt_UF_FunAppDiscount + (size - 20))
- | otherwise = emptyBag
- -- If the function is an argument and is applied
- -- to some values, give it an arg-discount
-
- -- See Note [Function application discount]
- res_discount | idArity fun > n_val_args = opt_UF_FunAppDiscount + (size - 20)
- | otherwise = 0
- -- If the function is partially applied, show a result discount
size | some_val_args = 10 * (1 + n_val_args)
| otherwise = 0
-- The 1+ is for the function itself
-- Add 1 for each non-trivial arg;
-- the allocation cost, as in let(rec)
+ -- DISCOUNTS
+ -- See Note [Function application discounts]
+ arg_discount | some_val_args && one_call fun top_args
+ = unitBag (fun, opt_UF_FunAppDiscount)
+ | otherwise = emptyBag
+ -- If the function is an argument and is applied
+ -- to some values, give it an arg-discount
+
+ res_discount | idArity fun > n_val_args = opt_UF_FunAppDiscount
+ | otherwise = 0
+ -- If the function is partially applied, show a result discount
+
+ one_call _ [] = False
+ one_call fun (arg:args) | fun==arg = case idOccInfo arg of
+ OneOcc _ one_branch _ -> one_branch
+ _ -> False
+ | otherwise = one_call fun args
conSize :: DataCon -> Int -> ExprSize
conSize dc n_val_args
@@ -648,6 +581,21 @@ conSize dc n_val_args
-- [SDM, 25/5/11]
\end{code}
+Note [Function application discount]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We want a discount if the function is applied. A good example is
+monadic combinators with continuation arguments, where inlining is
+quite important.
+
+But we don't want a big discount when a function is called many times
+(see the detailed comments with Trac #6048) because if the function is
+big it won't be inlined at its many call sites and no benefit results.
+Indeed, we can get exponentially big inlinings this way; that is what
+Trac #6048 is about.
+
+So, we only give a function-application discount when the function appears
+textually once, albeit possibly inside a lambda.
+
Note [Literal integer size]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Literal integers *can* be big (mkInteger [...coefficients...]), but
@@ -918,11 +866,11 @@ callSiteInline dflags id active_unfolding lone_variable arg_infos cont_info
-- Things with an INLINE pragma may have an unfolding *and*
-- be a loop breaker (maybe the knot is not yet untied)
CoreUnfolding { uf_tmpl = unf_template, uf_is_top = is_top
- , uf_is_cheap = is_cheap, uf_arity = uf_arity
+ , uf_is_work_free = is_wf, uf_arity = uf_arity
, uf_guidance = guidance, uf_expandable = is_exp }
| active_unfolding -> tryUnfolding dflags id lone_variable
arg_infos cont_info unf_template is_top
- is_cheap is_exp uf_arity guidance
+ is_wf is_exp uf_arity guidance
| dopt Opt_D_dump_inlinings dflags && dopt Opt_D_verbose_core2core dflags
-> pprTrace "Inactive unfolding:" (ppr id) Nothing
| otherwise -> Nothing
@@ -935,7 +883,7 @@ tryUnfolding :: DynFlags -> Id -> Bool -> [ArgSummary] -> CallCtxt
-> Maybe CoreExpr
tryUnfolding dflags id lone_variable
arg_infos cont_info unf_template is_top
- is_cheap is_exp uf_arity guidance
+ is_wf is_exp uf_arity guidance
-- uf_arity will typically be equal to (idArity id),
-- but may be less for InlineRules
| dopt Opt_D_dump_inlinings dflags && dopt Opt_D_verbose_core2core dflags
@@ -945,7 +893,7 @@ tryUnfolding dflags id lone_variable
text "interesting continuation" <+> ppr cont_info,
text "some_benefit" <+> ppr some_benefit,
text "is exp:" <+> ppr is_exp,
- text "is cheap:" <+> ppr is_cheap,
+ text "is work-free:" <+> ppr is_wf,
text "guidance" <+> ppr guidance,
extra_doc,
text "ANSWER =" <+> if yes_or_no then text "YES" else text "NO"])
@@ -979,7 +927,7 @@ tryUnfolding dflags id lone_variable
interesting_saturated_call
= case cont_info of
BoringCtxt -> not is_top && uf_arity > 0 -- Note [Nested functions]
- CaseCtxt -> not (lone_variable && is_cheap) -- Note [Lone variables]
+ CaseCtxt -> not (lone_variable && is_wf) -- Note [Lone variables]
ArgCtxt {} -> uf_arity > 0 -- Note [Inlining in ArgCtxt]
ValAppCtxt -> True -- Note [Cast then apply]
@@ -993,7 +941,7 @@ tryUnfolding dflags id lone_variable
enough_args = saturated || (unsat_ok && n_val_args > 0)
UnfIfGoodArgs { ug_args = arg_discounts, ug_res = res_discount, ug_size = size }
- -> ( is_cheap && some_benefit && small_enough
+ -> ( is_wf && some_benefit && small_enough
, (text "discounted size =" <+> int discounted_size) )
where
discounted_size = size - discount
@@ -1105,7 +1053,7 @@ call is at least CONLIKE. At least for the cases where we use ArgCtxt
for the RHS of a 'let', we only profit from the inlining if we get a
CONLIKE thing (modulo lets).
-Note [Lone variables] See also Note [Interaction of exprIsCheap and lone variables]
+Note [Lone variables] See also Note [Interaction of exprIsWorkFree and lone variables]
~~~~~~~~~~~~~~~~~~~~~ which appears below
The "lone-variable" case is important. I spent ages messing about
with unsatisfactory varaints, but this is nice. The idea is that if a
@@ -1152,7 +1100,7 @@ However, watch out:
So the non-inlining of lone_variables should only apply if the
unfolding is regarded as cheap; because that is when exprIsConApp_maybe
- looks through the unfolding. Hence the "&& is_cheap" in the
+ looks through the unfolding. Hence the "&& is_wf" in the
InlineRule branch.
* Even a type application or coercion isn't a lone variable.
@@ -1167,7 +1115,7 @@ However, watch out:
There's no advantage in inlining f here, and perhaps
a significant disadvantage. Hence some_val_args in the Stop case
-Note [Interaction of exprIsCheap and lone variables]
+Note [Interaction of exprIsWorkFree and lone variables]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The lone-variable test says "don't inline if a case expression
scrutines a lone variable whose unfolding is cheap". It's very
@@ -1178,9 +1126,9 @@ consider
to be cheap, and that's good because exprIsConApp_maybe doesn't
think that expression is a constructor application.
-I used to test is_value rather than is_cheap, which was utterly
-wrong, because the above expression responds True to exprIsHNF,
-which is what sets is_value.
+In the 'not (lone_variable && is_wf)' test, I used to test is_value
+rather than is_wf, which was utterly wrong, because the above
+expression responds True to exprIsHNF, which is what sets is_value.
This kind of thing can occur if you have
diff --git a/compiler/coreSyn/CoreUtils.lhs b/compiler/coreSyn/CoreUtils.lhs
index 8ec132f993..34046e8159 100644
--- a/compiler/coreSyn/CoreUtils.lhs
+++ b/compiler/coreSyn/CoreUtils.lhs
@@ -22,7 +22,7 @@ module CoreUtils (
exprType, coreAltType, coreAltsType,
exprIsDupable, exprIsTrivial, getIdFromTrivialExpr, exprIsBottom,
exprIsCheap, exprIsExpandable, exprIsCheap', CheapAppFun,
- exprIsHNF, exprOkForSpeculation, exprOkForSideEffects,
+ exprIsHNF, exprOkForSpeculation, exprOkForSideEffects, exprIsWorkFree,
exprIsBig, exprIsConLike,
rhsIsStatic, isCheapApp, isExpandableApp,
@@ -187,15 +187,7 @@ mkCast (Coercion e_co) co
-- The guard here checks that g has a (~#) on both sides,
-- otherwise decomposeCo fails. Can in principle happen
-- with unsafeCoerce
- = Coercion new_co
- where
- -- g :: (s1 ~# s2) ~# (t1 ~# t2)
- -- g1 :: s1 ~# t1
- -- g2 :: s2 ~# t2
- new_co = mkSymCo g1 `mkTransCo` e_co `mkTransCo` g2
- [_reflk, g1, g2] = decomposeCo 3 co
- -- Remember, (~#) :: forall k. k -> k -> *
- -- so it takes *three* arguments, not two
+ = Coercion (mkCoCast e_co co)
mkCast (Cast expr co2) co
= ASSERT(let { Pair from_ty _to_ty = coercionKind co;
@@ -640,6 +632,68 @@ dupAppSize = 8 -- Size of term we are prepared to duplicate
%* *
%************************************************************************
+Note [exprIsWorkFree]
+~~~~~~~~~~~~~~~~~~~~~
+exprIsWorkFree is used when deciding whether to inline something; we
+don't inline it if doing so might duplicate work, by peeling off a
+complete copy of the expression. Here we do not want even to
+duplicate a primop (Trac #5623):
+ eg let x = a #+ b in x +# x
+ we do not want to inline/duplicate x
+
+Previously we were a bit more liberal, which led to the primop-duplicating
+problem. However, being more conservative did lead to a big regression in
+one nofib benchmark, wheel-sieve1. The situation looks like this:
+
+ let noFactor_sZ3 :: GHC.Types.Int -> GHC.Types.Bool
+ noFactor_sZ3 = case s_adJ of _ { GHC.Types.I# x_aRs ->
+ case GHC.Prim.<=# x_aRs 2 of _ {
+ GHC.Types.False -> notDivBy ps_adM qs_adN;
+ GHC.Types.True -> lvl_r2Eb }}
+ go = \x. ...(noFactor (I# y))....(go x')...
+
+The function 'noFactor' is heap-allocated and then called. Turns out
+that 'notDivBy' is strict in its THIRD arg, but that is invisible to
+the caller of noFactor, which therefore cannot do w/w and
+heap-allocates noFactor's argument. At the moment (May 12) we are just
+going to put up with this, because the previous more aggressive inlining
+(which treated 'noFactor' as work-free) was duplicating primops, which
+in turn was making inner loops of array calculations runs slow (#5623)
+
+\begin{code}
+exprIsWorkFree :: CoreExpr -> Bool
+-- See Note [exprIsWorkFree]
+exprIsWorkFree e = go 0 e
+ where -- n is the number of value arguments
+ go _ (Lit {}) = True
+ go _ (Type {}) = True
+ go _ (Coercion {}) = True
+ go n (Cast e _) = go n e
+ go n (Case scrut _ _ alts) = foldl (&&) (exprIsWorkFree scrut)
+ [ go n rhs | (_,_,rhs) <- alts ]
+ -- See Note [Case expressions are work-free]
+ go _ (Let {}) = False
+ go n (Var v) = n==0 || n < idArity v
+ go n (Tick t e) | tickishCounts t = False
+ | otherwise = go n e
+ go n (Lam x e) | isRuntimeVar x = n==0 || go (n-1) e
+ | otherwise = go n e
+ go n (App f e) | isRuntimeArg e = exprIsWorkFree e && go (n+1) f
+ | otherwise = go n f
+\end{code}
+
+Note [Case expressions are work-free]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Are case-expressions work-free? Consider
+ let v = case x of (p,q) -> p
+ go = \y -> ...case v of ...
+Should we inline 'v' at its use site inside the loop? At the moment
+we do. I experimented with saying that case are *not* work-free, but
+that increased allocation slightly. It's a fairly small effect, and at
+the moment we go for the slightly more aggressive version which treats
+(case x of ....) as work-free if the alterantives are.
+
+
Note [exprIsCheap] See also Note [Interaction of exprIsCheap and lone variables]
~~~~~~~~~~~~~~~~~~ in CoreUnfold.lhs
@exprIsCheap@ looks at a Core expression and returns \tr{True} if
diff --git a/compiler/coreSyn/PprCore.lhs b/compiler/coreSyn/PprCore.lhs
index d98a4ad734..9504b14ee5 100644
--- a/compiler/coreSyn/PprCore.lhs
+++ b/compiler/coreSyn/PprCore.lhs
@@ -419,7 +419,7 @@ instance Outputable Unfolding where
<+> ppr con <+> brackets (pprWithCommas ppr ops)
ppr (CoreUnfolding { uf_src = src
, uf_tmpl=rhs, uf_is_top=top, uf_is_value=hnf
- , uf_is_conlike=conlike, uf_is_cheap=cheap
+ , uf_is_conlike=conlike, uf_is_work_free=wf
, uf_expandable=exp, uf_guidance=g, uf_arity=arity})
= ptext (sLit "Unf") <> braces (pp_info $$ pp_rhs)
where
@@ -429,7 +429,7 @@ instance Outputable Unfolding where
, ptext (sLit "Arity=") <> int arity
, ptext (sLit "Value=") <> ppr hnf
, ptext (sLit "ConLike=") <> ppr conlike
- , ptext (sLit "Cheap=") <> ppr cheap
+ , ptext (sLit "WorkFree=") <> ppr wf
, ptext (sLit "Expandable=") <> ppr exp
, ptext (sLit "Guidance=") <> ppr g ]
pp_tmpl = ptext (sLit "Tmpl=") <+> ppr rhs
diff --git a/compiler/deSugar/DsBinds.lhs b/compiler/deSugar/DsBinds.lhs
index 8fc6bd91f3..eae9530b0e 100644
--- a/compiler/deSugar/DsBinds.lhs
+++ b/compiler/deSugar/DsBinds.lhs
@@ -18,7 +18,7 @@ lower levels it is preserved with @let@/@letrec@s).
-- for details
module DsBinds ( dsTopLHsBinds, dsLHsBinds, decomposeRuleLhs, dsSpec,
- dsHsWrapper, dsTcEvBinds, dsEvBinds, dsTcCoercion
+ dsHsWrapper, dsTcEvBinds, dsEvBinds
) where
#include "HsVersions.h"
@@ -32,7 +32,6 @@ import DsUtils
import HsSyn -- lots of things
import CoreSyn -- lots of things
-import HscTypes ( MonadThings )
import Literal ( Literal(MachStr) )
import CoreSubst
import MkCore
@@ -40,6 +39,8 @@ import CoreUtils
import CoreArity ( etaExpand )
import CoreUnfold
import CoreFVs
+import UniqSupply
+import Unique( Unique )
import Digraph
@@ -52,7 +53,7 @@ import TysWiredIn ( eqBoxDataCon, tupleCon )
import Id
import Class
import DataCon ( dataConWorkId )
-import Name ( Name, localiseName )
+import Name
import MkId ( seqId )
import Var
import VarSet
@@ -662,7 +663,7 @@ but it seems better to reject the program because it's almost certainly
a mistake. That's what the isDeadBinder call detects.
Note [Constant rule dicts]
-~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~
When the LHS of a specialisation rule, (/\as\ds. f es) has a free dict,
which is presumably in scope at the function definition site, we can quantify
over it too. *Any* dict with that type will do.
@@ -695,23 +696,23 @@ as the old one, but with an Internal name and no IdInfo.
\begin{code}
-dsHsWrapper :: MonadThings m => HsWrapper -> CoreExpr -> m CoreExpr
+dsHsWrapper :: HsWrapper -> CoreExpr -> DsM CoreExpr
dsHsWrapper WpHole e = return e
dsHsWrapper (WpTyApp ty) e = return $ App e (Type ty)
dsHsWrapper (WpLet ev_binds) e = do bs <- dsTcEvBinds ev_binds
return (mkCoreLets bs e)
dsHsWrapper (WpCompose c1 c2) e = dsHsWrapper c1 =<< dsHsWrapper c2 e
-dsHsWrapper (WpCast co) e = return $ dsTcCoercion co (mkCast e)
+dsHsWrapper (WpCast co) e = dsTcCoercion co (mkCast e)
dsHsWrapper (WpEvLam ev) e = return $ Lam ev e
dsHsWrapper (WpTyLam tv) e = return $ Lam tv e
dsHsWrapper (WpEvApp evtrm) e = liftM (App e) (dsEvTerm evtrm)
--------------------------------------
-dsTcEvBinds :: MonadThings m => TcEvBinds -> m [CoreBind]
+dsTcEvBinds :: TcEvBinds -> DsM [CoreBind]
dsTcEvBinds (TcEvBinds {}) = panic "dsEvBinds" -- Zonker has got rid of this
dsTcEvBinds (EvBinds bs) = dsEvBinds bs
-dsEvBinds :: MonadThings m => Bag EvBind -> m [CoreBind]
+dsEvBinds :: Bag EvBind -> DsM [CoreBind]
dsEvBinds bs = mapM ds_scc (sccEvBinds bs)
where
ds_scc (AcyclicSCC (EvBind v r)) = liftM (NonRec v) (dsEvTerm r)
@@ -726,39 +727,51 @@ sccEvBinds bs = stronglyConnCompFromEdgedVertices edges
edges = foldrBag ((:) . mk_node) [] bs
mk_node :: EvBind -> (EvBind, EvVar, [EvVar])
- mk_node b@(EvBind var term) = (b, var, evVarsOfTerm term)
+ mk_node b@(EvBind var term) = (b, var, varSetElems (evVarsOfTerm term))
---------------------------------------
-dsEvTerm :: MonadThings m => EvTerm -> m CoreExpr
+dsEvTerm :: EvTerm -> DsM CoreExpr
dsEvTerm (EvId v) = return (Var v)
-dsEvTerm (EvCast v co)
- = return $ dsTcCoercion co $ mkCast (Var v) -- 'v' is always a lifted evidence variable so it is
- -- unnecessary to call varToCoreExpr v here.
+dsEvTerm (EvCast tm co)
+ = do { tm' <- dsEvTerm tm
+ ; dsTcCoercion co $ mkCast tm' }
+ -- 'v' is always a lifted evidence variable so it is
+ -- unnecessary to call varToCoreExpr v here.
+
dsEvTerm (EvKindCast v co)
- = return $ dsTcCoercion co $ (\_ -> Var v)
+ = do { v' <- dsEvTerm v
+ ; dsTcCoercion co $ (\_ -> v') }
-dsEvTerm (EvDFunApp df tys vars) = return (Var df `mkTyApps` tys `mkVarApps` vars)
-dsEvTerm (EvCoercion co) = return $ dsTcCoercion co mkEqBox
+dsEvTerm (EvDFunApp df tys tms) = do { tms' <- mapM dsEvTerm tms
+ ; return (Var df `mkTyApps` tys `mkApps` tms') }
+dsEvTerm (EvCoercion co) = dsTcCoercion co mkEqBox
dsEvTerm (EvTupleSel v n)
- = ASSERT( isTupleTyCon tc )
- return $
- Case (Var v) (mkWildValBinder (varType v)) (tys !! n) [(DataAlt dc, xs, Var v')]
- where
- (tc, tys) = splitTyConApp (evVarPred v)
- Just [dc] = tyConDataCons_maybe tc
- v' = v `setVarType` ty_want
- xs = map mkWildValBinder tys_before ++ v' : map mkWildValBinder tys_after
- (tys_before, ty_want:tys_after) = splitAt n tys
-dsEvTerm (EvTupleMk vs) = return $ Var (dataConWorkId dc) `mkTyApps` tys `mkVarApps` vs
- where dc = tupleCon ConstraintTuple (length vs)
- tys = map varType vs
+ = do { tm' <- dsEvTerm v
+ ; let scrut_ty = exprType tm'
+ (tc, tys) = splitTyConApp scrut_ty
+ Just [dc] = tyConDataCons_maybe tc
+ xs = mkTemplateLocals tys
+ the_x = xs !! n
+ ; ASSERT( isTupleTyCon tc )
+ return $
+ Case tm' (mkWildValBinder scrut_ty) (idType the_x) [(DataAlt dc, xs, Var the_x)] }
+
+dsEvTerm (EvTupleMk tms)
+ = do { tms' <- mapM dsEvTerm tms
+ ; let tys = map exprType tms'
+ ; return $ Var (dataConWorkId dc) `mkTyApps` tys `mkApps` tms' }
+ where
+ dc = tupleCon ConstraintTuple (length tms)
+
dsEvTerm (EvSuperClass d n)
- = return $ Var sc_sel_id `mkTyApps` tys `App` Var d
+ = do { d' <- dsEvTerm d
+ ; let (cls, tys) = getClassPredTys (exprType d')
+ sc_sel_id = classSCSelId cls n -- Zero-indexed
+ ; return $ Var sc_sel_id `mkTyApps` tys `App` d' }
where
- sc_sel_id = classSCSelId cls n -- Zero-indexed
- (cls, tys) = getClassPredTys (evVarPred d)
+
dsEvTerm (EvDelayedError ty msg) = return $ Var errorId `mkTyApps` [ty] `mkApps` [litMsg]
where
errorId = rUNTIME_ERROR_ID
@@ -770,7 +783,7 @@ dsEvTerm (EvLit l) =
EvStr s -> mkStringExprFS s
---------------------------------------
-dsTcCoercion :: TcCoercion -> (Coercion -> CoreExpr) -> CoreExpr
+dsTcCoercion :: TcCoercion -> (Coercion -> CoreExpr) -> DsM CoreExpr
-- This is the crucial function that moves
-- from TcCoercions to Coercions; see Note [TcCoercions] in Coercion
-- e.g. dsTcCoercion (trans g1 g2) k
@@ -778,22 +791,28 @@ dsTcCoercion :: TcCoercion -> (Coercion -> CoreExpr) -> CoreExpr
-- case g2 of EqBox g2# ->
-- k (trans g1# g2#)
dsTcCoercion co thing_inside
- = foldr wrap_in_case result_expr eqvs_covs
- where
- result_expr = thing_inside (ds_tc_coercion subst co)
- result_ty = exprType result_expr
+ = do { us <- newUniqueSupply
+ ; let eqvs_covs :: [(EqVar,CoVar)]
+ eqvs_covs = zipWith mk_co_var (varSetElems (coVarsOfTcCo co))
+ (uniqsFromSupply us)
- -- We use the same uniques for the EqVars and the CoVars, and just change
- -- the type. So the CoVars shadow the EqVars
+ subst = mkCvSubst emptyInScopeSet [(eqv, mkCoVarCo cov) | (eqv, cov) <- eqvs_covs]
+ result_expr = thing_inside (ds_tc_coercion subst co)
+ result_ty = exprType result_expr
- eqvs_covs :: [(EqVar,CoVar)]
- eqvs_covs = [(eqv, eqv `setIdType` mkCoercionType ty1 ty2)
- | eqv <- varSetElems (coVarsOfTcCo co)
- , let (ty1, ty2) = getEqPredTys (evVarPred eqv)]
- subst = mkCvSubst emptyInScopeSet [(eqv, mkCoVarCo cov) | (eqv, cov) <- eqvs_covs]
-
- wrap_in_case (eqv, cov) body
+ ; return (foldr (wrap_in_case result_ty) result_expr eqvs_covs) }
+ where
+ mk_co_var :: Id -> Unique -> (Id, Id)
+ mk_co_var eqv uniq = (eqv, mkUserLocal occ uniq ty loc)
+ where
+ eq_nm = idName eqv
+ occ = nameOccName eq_nm
+ loc = nameSrcSpan eq_nm
+ ty = mkCoercionType ty1 ty2
+ (ty1, ty2) = getEqPredTys (evVarPred eqv)
+
+ wrap_in_case result_ty (eqv, cov) body
= Case (Var eqv) eqv result_ty [(DataAlt eqBoxDataCon, [cov], body)]
ds_tc_coercion :: CvSubst -> TcCoercion -> Coercion
@@ -816,6 +835,7 @@ ds_tc_coercion subst tc_co
go (TcNthCo n co) = mkNthCo n (go co)
go (TcInstCo co ty) = mkInstCo (go co) ty
go (TcLetCo bs co) = ds_tc_coercion (ds_co_binds bs) co
+ go (TcCastCo co1 co2) = mkCoCast (go co1) (go co2)
go (TcCoVarCo v) = ds_ev_id subst v
ds_co_binds :: TcEvBinds -> CvSubst
diff --git a/compiler/deSugar/DsMeta.hs b/compiler/deSugar/DsMeta.hs
index 060b63d46e..98aec5f167 100644
--- a/compiler/deSugar/DsMeta.hs
+++ b/compiler/deSugar/DsMeta.hs
@@ -150,7 +150,8 @@ repTopDs group
hsSigTvBinders :: HsValBinds Name -> [Name]
-- See Note [Scoped type variables in bindings]
hsSigTvBinders binds
- = [hsLTyVarName tv | L _ (TypeSig _ (L _ (HsForAllTy Explicit tvs _ _))) <- sigs, tv <- tvs]
+ = [hsLTyVarName tv | L _ (TypeSig _ (L _ (HsForAllTy Explicit qtvs _ _))) <- sigs
+ , tv <- hsQTvBndrs qtvs]
where
sigs = case binds of
ValBindsIn _ sigs -> sigs
@@ -214,9 +215,8 @@ repTyClD (L loc (TyFamily { tcdFlavour = flavour,
do { flav <- repFamilyFlavour flavour
; case opt_kind of
Nothing -> repFamilyNoKind flav tc1 bndrs
- Just (HsBSig ki _)
- -> do { ki1 <- repKind ki
- ; repFamilyKind flav tc1 bndrs ki1 }
+ Just ki -> do { ki1 <- repKind ki
+ ; repFamilyKind flav tc1 bndrs ki1 }
}
; return $ Just (loc, dec)
}
@@ -272,15 +272,15 @@ repTyDefn tc bndrs opt_tys _ (TySynonym { td_synRhs = ty })
; repTySyn tc bndrs opt_tys ty1 }
-------------------------
-mk_extra_tvs :: Located Name -> [LHsTyVarBndr Name]
- -> HsTyDefn Name -> DsM [LHsTyVarBndr Name]
+mk_extra_tvs :: Located Name -> LHsTyVarBndrs Name
+ -> HsTyDefn Name -> DsM (LHsTyVarBndrs Name)
-- If there is a kind signature it must be of form
-- k1 -> .. -> kn -> *
-- Return type variables [tv1:k1, tv2:k2, .., tvn:kn]
mk_extra_tvs tc tvs defn
- | TyData { td_kindSig = Just (HsBSig hs_kind _) } <- defn
+ | TyData { td_kindSig = Just hs_kind } <- defn
= do { extra_tvs <- go hs_kind
- ; return (tvs ++ extra_tvs) }
+ ; return (mkHsQTvs (hsQTvBndrs tvs ++ extra_tvs)) }
| otherwise
= return tvs
where
@@ -289,7 +289,7 @@ mk_extra_tvs tc tvs defn
= do { uniq <- newUnique
; let { occ = mkTyVarOccFS (fsLit "t")
; nm = mkInternalName uniq occ loc
- ; hs_tv = L loc (KindedTyVar nm (mkHsBSig kind)) }
+ ; hs_tv = L loc (KindedTyVar nm kind) }
; hs_tvs <- go rest
; return (hs_tv : hs_tvs) }
@@ -340,7 +340,7 @@ repInstD (L loc (ClsInstD { cid_poly_ty = ty, cid_binds = binds
-- the selector Ids, not to fresh names (Trac #5410)
--
do { cxt1 <- repContext cxt
- ; cls_tcon <- repTy (HsTyVar cls)
+ ; cls_tcon <- repTy (HsTyVar (unLoc cls))
; cls_tys <- repLTys tys
; inst_ty1 <- repTapps cls_tcon cls_tys
; binds1 <- rep_binds binds
@@ -350,17 +350,17 @@ repInstD (L loc (ClsInstD { cid_poly_ty = ty, cid_binds = binds
; repInst cxt1 inst_ty1 decls }
; return (loc, dec) }
where
- Just (tvs, cxt, cls, tys) = splitHsInstDeclTy_maybe (unLoc ty)
+ Just (tvs, cxt, cls, tys) = splitLHsInstDeclTy_maybe ty
repFamInstD :: FamInstDecl Name -> DsM (Core TH.DecQ)
repFamInstD (FamInstDecl { fid_tycon = tc_name
- , fid_pats = HsBSig tys (kv_names, tv_names)
+ , fid_pats = HsWB { hswb_cts = tys, hswb_kvs = kv_names, hswb_tvs = tv_names }
, fid_defn = defn })
= WARN( not (null kv_names), ppr kv_names ) -- We have not yet dealt with kind
-- polymorphism in Template Haskell (sigh)
do { tc <- lookupLOcc tc_name -- See note [Binders and occurrences]
; let loc = getLoc tc_name
- hs_tvs = [ L loc (UserTyVar n) | n <- tv_names] -- Yuk
+ hs_tvs = mkHsQTvs (userHsTyVarBndrs loc tv_names) -- Yuk
; addTyClTyVarBinds hs_tvs $ \ bndrs ->
do { tys1 <- repLTys tys
; tys2 <- coreList typeQTyConName tys1
@@ -419,8 +419,9 @@ ds_msg = ptext (sLit "Cannot desugar this Template Haskell declaration:")
-------------------------------------------------------
repC :: [Name] -> LConDecl Name -> DsM (Core TH.ConQ)
-repC _ (L _ (ConDecl { con_name = con, con_qvars = [], con_cxt = L _ []
+repC _ (L _ (ConDecl { con_name = con, con_qvars = con_tvs, con_cxt = L _ []
, con_details = details, con_res = ResTyH98 }))
+ | null (hsQTvBndrs con_tvs)
= do { con1 <- lookupLOcc con -- See note [Binders and occurrences]
; repConstr con1 details }
repC tvs (L _ (ConDecl { con_name = con
@@ -428,7 +429,7 @@ repC tvs (L _ (ConDecl { con_name = con
, con_details = details
, con_res = res_ty }))
= do { (eq_ctxt, con_tv_subst) <- mkGadtCtxt tvs res_ty
- ; let ex_tvs = [ tv | tv <- con_tvs, not (hsLTyVarName tv `in_subst` con_tv_subst)]
+ ; let ex_tvs = mkHsQTvs [ tv | tv <- hsQTvBndrs con_tvs, not (hsLTyVarName tv `in_subst` con_tv_subst)]
; binds <- mapM dupBinder con_tv_subst
; dsExtendMetaEnv (mkNameEnv binds) $ -- Binds some of the con_tvs
addTyVarBinds ex_tvs $ \ ex_bndrs -> -- Binds the remaining con_tvs
@@ -552,7 +553,7 @@ rep_ty_sig loc (L _ ty) nm
rep_ty (HsForAllTy Explicit tvs ctxt ty)
= do { let rep_in_scope_tv tv = do { name <- lookupBinder (hsLTyVarName tv)
; repTyVarBndrWithKind tv name }
- ; bndrs1 <- mapM rep_in_scope_tv tvs
+ ; bndrs1 <- mapM rep_in_scope_tv (hsQTvBndrs tvs)
; bndrs2 <- coreList tyVarBndrTyConName bndrs1
; ctxt1 <- repLContext ctxt
; ty1 <- repLTy ty
@@ -616,7 +617,7 @@ rep_InlinePrag (InlinePragma { inl_act = activation, inl_rule = match, inl_inlin
-- Types
-------------------------------------------------------
-addTyVarBinds :: [LHsTyVarBndr Name] -- the binders to be added
+addTyVarBinds :: LHsTyVarBndrs Name -- the binders to be added
-> (Core [TH.TyVarBndr] -> DsM (Core (TH.Q a))) -- action in the ext env
-> DsM (Core (TH.Q a))
-- gensym a list of type variables and enter them into the meta environment;
@@ -626,14 +627,14 @@ addTyVarBinds :: [LHsTyVarBndr Name] -- the binders to be
addTyVarBinds tvs m
= do { freshNames <- mkGenSyms (hsLTyVarNames tvs)
; term <- addBinds freshNames $
- do { kbs1 <- mapM mk_tv_bndr (tvs `zip` freshNames)
+ do { kbs1 <- mapM mk_tv_bndr (hsQTvBndrs tvs `zip` freshNames)
; kbs2 <- coreList tyVarBndrTyConName kbs1
; m kbs2 }
; wrapGenSyms freshNames term }
where
mk_tv_bndr (tv, (_,v)) = repTyVarBndrWithKind tv (coreVar v)
-addTyClTyVarBinds :: [LHsTyVarBndr Name]
+addTyClTyVarBinds :: LHsTyVarBndrs Name
-> (Core [TH.TyVarBndr] -> DsM (Core (TH.Q a)))
-> DsM (Core (TH.Q a))
@@ -650,7 +651,7 @@ addTyClTyVarBinds tvs m
-- This makes things work for family declarations
; term <- addBinds freshNames $
- do { kbs1 <- mapM mk_tv_bndr tvs
+ do { kbs1 <- mapM mk_tv_bndr (hsQTvBndrs tvs)
; kbs2 <- coreList tyVarBndrTyConName kbs1
; m kbs2 }
@@ -665,7 +666,7 @@ repTyVarBndrWithKind :: LHsTyVarBndr Name
-> Core TH.Name -> DsM (Core TH.TyVarBndr)
repTyVarBndrWithKind (L _ (UserTyVar {})) nm
= repPlainTV nm
-repTyVarBndrWithKind (L _ (KindedTyVar _ (HsBSig ki _))) nm
+repTyVarBndrWithKind (L _ (KindedTyVar _ ki)) nm
= repKind ki >>= repKindedTV nm
-- represent a type context
diff --git a/compiler/ghci/ByteCodeGen.lhs b/compiler/ghci/ByteCodeGen.lhs
index c8b1b303b5..c84d84a78c 100644
--- a/compiler/ghci/ByteCodeGen.lhs
+++ b/compiler/ghci/ByteCodeGen.lhs
@@ -482,6 +482,9 @@ schemeE d s p exp@(AnnTick (Breakpoint _id _fvs) _rhs)
-- ignore other kinds of tick
schemeE d s p (AnnTick _ (_, rhs)) = schemeE d s p rhs
+schemeE d s p (AnnCase (_,scrut) _ _ []) = schemeE d s p scrut
+ -- no alts: scrut is guaranteed to diverge
+
schemeE d s p (AnnCase scrut _ _ [(DataAlt dc, [bind1, bind2], rhs)])
| isUnboxedTupleCon dc, VoidArg <- typeCgRep (idType bind1)
-- Convert
diff --git a/compiler/hsSyn/Convert.lhs b/compiler/hsSyn/Convert.lhs
index 7e8ceb6695..8d5ad6b4f0 100644
--- a/compiler/hsSyn/Convert.lhs
+++ b/compiler/hsSyn/Convert.lhs
@@ -275,7 +275,7 @@ cvt_ci_decs doc decs
cvt_tycl_hdr :: TH.Cxt -> TH.Name -> [TH.TyVarBndr]
-> CvtM ( LHsContext RdrName
, Located RdrName
- , [LHsTyVarBndr RdrName])
+ , LHsTyVarBndrs RdrName)
cvt_tycl_hdr cxt tc tvs
= do { cxt' <- cvtContext cxt
; tc' <- tconNameL tc
@@ -286,12 +286,12 @@ cvt_tycl_hdr cxt tc tvs
cvt_tyinst_hdr :: TH.Cxt -> TH.Name -> [TH.Type]
-> CvtM ( LHsContext RdrName
, Located RdrName
- , HsBndrSig [LHsType RdrName])
+ , HsWithBndrs [LHsType RdrName])
cvt_tyinst_hdr cxt tc tys
= do { cxt' <- cvtContext cxt
; tc' <- tconNameL tc
; tys' <- mapM cvtType tys
- ; return (cxt', tc', mkHsBSig tys') }
+ ; return (cxt', tc', mkHsWithBndrs tys') }
-------------------------------------------------------------------
-- Partitioning declarations
@@ -348,7 +348,7 @@ cvtConstr (ForallC tvs ctxt con)
= do { tvs' <- cvtTvs tvs
; L loc ctxt' <- cvtContext ctxt
; L _ con' <- cvtConstr con
- ; returnL $ con' { con_qvars = tvs' ++ con_qvars con'
+ ; returnL $ con' { con_qvars = mkHsQTvs (hsQTvBndrs tvs' ++ hsQTvBndrs (con_qvars con'))
, con_cxt = L loc (ctxt' ++ (unLoc $ con_cxt con')) } }
cvt_arg :: (TH.Strict, TH.Type) -> CvtM (LHsType RdrName)
@@ -759,7 +759,7 @@ cvtp (RecP c fs) = do { c' <- cNameL c; fs' <- mapM cvtPatFld fs
; return $ ConPatIn c' $ Hs.RecCon (HsRecFields fs' Nothing) }
cvtp (ListP ps) = do { ps' <- cvtPats ps; return $ ListPat ps' void }
cvtp (SigP p t) = do { p' <- cvtPat p; t' <- cvtType t
- ; return $ SigPatIn p' (mkHsBSig t') }
+ ; return $ SigPatIn p' (mkHsWithBndrs t') }
cvtp (ViewP e p) = do { e' <- cvtl e; p' <- cvtPat p; return $ ViewPat e' p' void }
cvtPatFld :: (TH.Name, TH.Pat) -> CvtM (HsRecField RdrName (LPat RdrName))
@@ -784,8 +784,8 @@ cvtOpAppP x op y
-----------------------------------------------------------
-- Types and type variables
-cvtTvs :: [TH.TyVarBndr] -> CvtM [LHsTyVarBndr RdrName]
-cvtTvs tvs = mapM cvt_tv tvs
+cvtTvs :: [TH.TyVarBndr] -> CvtM (LHsTyVarBndrs RdrName)
+cvtTvs tvs = do { tvs' <- mapM cvt_tv tvs; return (mkHsQTvs tvs') }
cvt_tv :: TH.TyVarBndr -> CvtM (LHsTyVarBndr RdrName)
cvt_tv (TH.PlainTV nm)
@@ -794,7 +794,7 @@ cvt_tv (TH.PlainTV nm)
cvt_tv (TH.KindedTV nm ki)
= do { nm' <- tName nm
; ki' <- cvtKind ki
- ; returnL $ KindedTyVar nm' (mkHsBSig ki') }
+ ; returnL $ KindedTyVar nm' ki' }
cvtContext :: TH.Cxt -> CvtM (LHsContext RdrName)
cvtContext tys = do { preds' <- mapM cvtPred tys; returnL preds' }
@@ -845,7 +845,7 @@ cvtType ty
-> do { tvs' <- cvtTvs tvs
; cxt' <- cvtContext cxt
; ty' <- cvtType ty
- ; returnL $ mkExplicitHsForAllTy tvs' cxt' ty'
+ ; returnL $ mkExplicitHsForAllTy (hsQTvBndrs tvs') cxt' ty'
}
SigT ty ki
@@ -875,10 +875,10 @@ cvtKind (ArrowK k1 k2) = do
k2' <- cvtKind k2
returnL (HsFunTy k1' k2')
-cvtMaybeKind :: Maybe TH.Kind -> CvtM (Maybe (HsBndrSig (LHsKind RdrName)))
+cvtMaybeKind :: Maybe TH.Kind -> CvtM (Maybe (LHsKind RdrName))
cvtMaybeKind Nothing = return Nothing
cvtMaybeKind (Just ki) = do { ki' <- cvtKind ki
- ; return (Just (mkHsBSig ki')) }
+ ; return (Just ki') }
-----------------------------------------------------------
cvtFixity :: TH.Fixity -> Hs.Fixity
diff --git a/compiler/hsSyn/HsDecls.lhs b/compiler/hsSyn/HsDecls.lhs
index c789a9efdc..cf1c2c9a8e 100644
--- a/compiler/hsSyn/HsDecls.lhs
+++ b/compiler/hsSyn/HsDecls.lhs
@@ -428,20 +428,20 @@ data TyClDecl name
| -- | @type/data family T :: *->*@
TyFamily { tcdFlavour :: FamilyFlavour, -- type or data
tcdLName :: Located name, -- type constructor
- tcdTyVars :: [LHsTyVarBndr name], -- type variables
- tcdKindSig :: Maybe (HsBndrSig (LHsKind name)) -- result kind
+ tcdTyVars :: LHsTyVarBndrs name, -- type variables
+ tcdKindSig :: Maybe (LHsKind name) -- result kind
}
| -- | @type/data declaration
TyDecl { tcdLName :: Located name -- ^ Type constructor
- , tcdTyVars :: [LHsTyVarBndr name]
+ , tcdTyVars :: LHsTyVarBndrs name
, tcdTyDefn :: HsTyDefn name
, tcdFVs :: NameSet }
| ClassDecl { tcdCtxt :: LHsContext name, -- ^ Context...
tcdLName :: Located name, -- ^ Name of the class
- tcdTyVars :: [LHsTyVarBndr name], -- ^ Class type variables
+ tcdTyVars :: LHsTyVarBndrs name, -- ^ Class type variables
tcdFDs :: [Located (FunDep name)], -- ^ Functional deps
tcdSigs :: [LSig name], -- ^ Methods' signatures
tcdMeths :: LHsBinds name, -- ^ Default methods
@@ -468,7 +468,7 @@ data HsTyDefn name -- The payload of a type synonym or data type defn
TyData { td_ND :: NewOrData,
td_ctxt :: LHsContext name, -- ^ Context
td_cType :: Maybe CType,
- td_kindSig:: Maybe (HsBndrSig (LHsKind name)),
+ td_kindSig:: Maybe (LHsKind name),
-- ^ Optional kind signature.
--
-- @(Just k)@ for a GADT-style @data@, or @data
@@ -619,18 +619,18 @@ instance OutputableBndr name
pp_vanilla_decl_head :: OutputableBndr name
=> Located name
- -> [LHsTyVarBndr name]
+ -> LHsTyVarBndrs name
-> HsContext name
-> SDoc
pp_vanilla_decl_head thing tyvars context
- = hsep [pprHsContext context, pprPrefixOcc (unLoc thing), interppSP tyvars]
+ = hsep [pprHsContext context, pprPrefixOcc (unLoc thing), ppr tyvars]
pp_fam_inst_head :: OutputableBndr name
=> Located name
- -> HsBndrSig [LHsType name]
+ -> HsWithBndrs [LHsType name]
-> HsContext name
-> SDoc
-pp_fam_inst_head thing (HsBSig typats _) context -- explicit type patterns
+pp_fam_inst_head thing (HsWB { hswb_cts = typats }) context -- explicit type patterns
= hsep [ ptext (sLit "instance"), pprHsContext context, pprPrefixOcc (unLoc thing)
, hsep (map (pprParendHsType.unLoc) typats)]
@@ -660,8 +660,8 @@ pp_ty_defn pp_hdr (TyData { td_ND = new_or_data, td_ctxt = L _ context
2 (pp_condecls condecls $$ pp_derivings)
where
pp_sig = case mb_sig of
- Nothing -> empty
- Just (HsBSig kind _) -> dcolon <+> ppr kind
+ Nothing -> empty
+ Just kind -> dcolon <+> ppr kind
pp_derivings = case derivings of
Nothing -> empty
Just ds -> hsep [ptext (sLit "deriving"), parens (interpp'SP ds)]
@@ -715,7 +715,7 @@ data ConDecl name
, con_explicit :: HsExplicitFlag
-- ^ Is there an user-written forall? (cf. 'HsTypes.HsForAllTy')
- , con_qvars :: [LHsTyVarBndr name]
+ , con_qvars :: LHsTyVarBndrs name
-- ^ Type variables. Depending on 'con_res' this describes the
-- following entities
--
@@ -808,8 +808,8 @@ type LFamInstDecl name = Located (FamInstDecl name)
data FamInstDecl name
= FamInstDecl
{ fid_tycon :: Located name
- , fid_pats :: HsBndrSig [LHsType name] -- ^ Type patterns (with bndrs)
- , fid_defn :: HsTyDefn name -- Type or data family instance
+ , fid_pats :: HsWithBndrs [LHsType name] -- ^ Type patterns (with kind and type bndrs)
+ , fid_defn :: HsTyDefn name -- Type or data family instance
, fid_fvs :: NameSet }
deriving( Typeable, Data )
@@ -1060,10 +1060,10 @@ data RuleDecl name
data RuleBndr name
= RuleBndr (Located name)
- | RuleBndrSig (Located name) (HsBndrSig (LHsType name))
+ | RuleBndrSig (Located name) (HsWithBndrs (LHsType name))
deriving (Data, Typeable)
-collectRuleBndrSigTys :: [RuleBndr name] -> [HsBndrSig (LHsType name)]
+collectRuleBndrSigTys :: [RuleBndr name] -> [HsWithBndrs (LHsType name)]
collectRuleBndrSigTys bndrs = [ty | RuleBndrSig _ ty <- bndrs]
instance OutputableBndr name => Outputable (RuleDecl name) where
diff --git a/compiler/hsSyn/HsPat.lhs b/compiler/hsSyn/HsPat.lhs
index 1a5e206a54..64bda890db 100644
--- a/compiler/hsSyn/HsPat.lhs
+++ b/compiler/hsSyn/HsPat.lhs
@@ -131,8 +131,8 @@ data Pat id
(SyntaxExpr id) -- Name of '-' (see RnEnv.lookupSyntaxName)
------------ Pattern type signatures ---------------
- | SigPatIn (LPat id) -- Pattern with a type signature
- (HsBndrSig (LHsType id))
+ | SigPatIn (LPat id) -- Pattern with a type signature
+ (HsWithBndrs (LHsType id)) -- Signature can bind both kind and type vars
| SigPatOut (LPat id) -- Pattern with a type signature
Type
diff --git a/compiler/hsSyn/HsTypes.lhs b/compiler/hsSyn/HsTypes.lhs
index 9a6679a68e..2504ad892e 100644
--- a/compiler/hsSyn/HsTypes.lhs
+++ b/compiler/hsSyn/HsTypes.lhs
@@ -17,7 +17,9 @@ HsTypes: Abstract syntax: user-defined types
module HsTypes (
HsType(..), LHsType, HsKind, LHsKind,
- HsBndrSig(..), HsTyVarBndr(..), LHsTyVarBndr,
+ HsTyVarBndr(..), LHsTyVarBndr,
+ LHsTyVarBndrs(..),
+ HsWithBndrs(..),
HsTupleSort(..), HsExplicitFlag(..),
HsContext, LHsContext,
HsQuasiQuote(..),
@@ -29,15 +31,14 @@ module HsTypes (
ConDeclField(..), pprConDeclFields,
+ mkHsQTvs, hsQTvBndrs,
mkExplicitHsForAllTy, mkImplicitHsForAllTy, hsExplicitTvs,
- hsTyVarName, hsTyVarNames,
+ hsTyVarName, hsTyVarNames, mkHsWithBndrs,
hsLTyVarName, hsLTyVarNames, hsLTyVarLocName, hsLTyVarLocNames,
- splitHsInstDeclTy_maybe, splitLHsInstDeclTy_maybe,
- splitHsForAllTy, splitLHsForAllTy,
+ splitLHsInstDeclTy_maybe,
splitHsClassTy_maybe, splitLHsClassTy_maybe,
splitHsFunType,
splitHsAppTys, mkHsAppTys, mkHsOpTy,
- placeHolderBndrs,
-- Printing
pprParendHsType, pprHsForAll, pprHsContext, ppr_hs_context,
@@ -112,6 +113,17 @@ getBangStrictness _ = HsNoBang
This is the syntax for types as seen in type signatures.
+Note [HsBSig binder lists]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider a binder (or pattern) decoarated with a type or kind,
+ \ (x :: a -> a). blah
+ forall (a :: k -> *) (b :: k). blah
+Then we use a LHsBndrSig on the binder, so that the
+renamer can decorate it with the variables bound
+by the pattern ('a' in the first example, 'k' in the second),
+assuming that neither of them is in scope already
+See also Note [Kind and type-variable binders] in RnTypes
+
\begin{code}
type LHsContext name = Located (HsContext name)
@@ -123,29 +135,29 @@ type LHsKind name = Located (HsKind name)
type LHsTyVarBndr name = Located (HsTyVarBndr name)
-data HsBndrSig sig
- = HsBSig
- sig -- The signature; typically a type
- ([Name], [Name]) -- The *binding* (kind, type) names of
- -- this signature
- -- See Note [HsBSig binder lists]
-
+data LHsTyVarBndrs name
+ = HsQTvs { hsq_kvs :: [Name] -- Kind variables
+ , hsq_tvs :: [LHsTyVarBndr name] -- Type variables
+ -- See Note [HsForAllTy tyvar binders]
+ }
+ deriving( Data, Typeable )
+
+mkHsQTvs :: [LHsTyVarBndr name] -> LHsTyVarBndrs name
+mkHsQTvs tvs = HsQTvs { hsq_kvs = panic "mkHsQTvs", hsq_tvs = tvs }
+
+hsQTvBndrs :: LHsTyVarBndrs name -> [LHsTyVarBndr name]
+hsQTvBndrs = hsq_tvs
+
+data HsWithBndrs thing
+ = HsWB { hswb_cts :: thing -- Main payload (type or list of types)
+ , hswb_kvs :: [Name] -- Kind vars
+ , hswb_tvs :: [Name] -- Type vars
+ }
deriving (Data, Typeable)
--- Note [HsBSig binder lists]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~
--- Consider a binder (or pattern) decoarated with a type or kind,
--- \ (x :: a -> a). blah
--- forall (a :: k -> *) (b :: k). blah
--- Then we use a LHsBndrSig on the binder, so that the
--- renamer can decorate it with the variables bound
--- by the pattern ('a' in the first example, 'k' in the second),
--- assuming that neither of them is in scope already
--- See also Note [Kind and type-variable binders] in RnTypes
-
-placeHolderBndrs :: [Name]
--- Used for the NameSet in FunBind and PatBind prior to the renamer
-placeHolderBndrs = panic "placeHolderBndrs"
+mkHsWithBndrs :: thing -> HsWithBndrs thing
+mkHsWithBndrs x = HsWB { hswb_cts = x, hswb_kvs = panic "mkHsTyWithBndrs:kvs"
+ , hswb_tvs = panic "mkHsTyWithBndrs:tvs" }
data HsTyVarBndr name
= UserTyVar -- No explicit kinding
@@ -153,17 +165,18 @@ data HsTyVarBndr name
| KindedTyVar
name
- (HsBndrSig (LHsKind name)) -- The user-supplied kind signature
+ (LHsKind name) -- The user-supplied kind signature
-- *** NOTA BENE *** A "monotype" in a pragma can have
-- for-alls in it, (mostly to do with dictionaries). These
-- must be explicitly Kinded.
deriving (Data, Typeable)
+
data HsType name
= HsForAllTy HsExplicitFlag -- Renamer leaves this flag unchanged, to record the way
-- the user wrote it originally, so that the printer can
-- print it as the user wrote it
- [LHsTyVarBndr name] -- See Note [HsForAllTy tyvar binders]
+ (LHsTyVarBndrs name)
(LHsContext name)
(LHsType name)
@@ -252,11 +265,11 @@ After renaming
* Implicit => the *type* variables free in the type
Explicit => the variables the user wrote (renamed)
-Note that in neither case do we inclde the kind variables.
-In the explicit case, the [HsTyVarBndr] can bring kind variables
-into scope: f :: forall (a::k->*) (b::k). a b -> Int
-but we do not record them explicitly, similar to the case
-for the type variables in a pattern type signature.
+The kind variables bound in the hsq_kvs field come both
+ a) from the kind signatures on the kind vars (eg k1)
+ b) from the scope of the forall (eg k2)
+Example: f :: forall (a::k1) b. T a (b::k2)
+
Note [Unit tuples]
~~~~~~~~~~~~~~~~~~
@@ -357,19 +370,19 @@ data ConDeclField name -- Record fields have Haddoc docs on them
mkImplicitHsForAllTy :: LHsContext name -> LHsType name -> HsType name
mkExplicitHsForAllTy :: [LHsTyVarBndr name] -> LHsContext name -> LHsType name -> HsType name
-mkImplicitHsForAllTy ctxt ty = mkHsForAllTy Implicit [] ctxt ty
+mkImplicitHsForAllTy ctxt ty = mkHsForAllTy Implicit [] ctxt ty
mkExplicitHsForAllTy tvs ctxt ty = mkHsForAllTy Explicit tvs ctxt ty
mkHsForAllTy :: HsExplicitFlag -> [LHsTyVarBndr name] -> LHsContext name -> LHsType name -> HsType name
-- Smart constructor for HsForAllTy
mkHsForAllTy exp tvs (L _ []) ty = mk_forall_ty exp tvs ty
-mkHsForAllTy exp tvs ctxt ty = HsForAllTy exp tvs ctxt ty
+mkHsForAllTy exp tvs ctxt ty = HsForAllTy exp (mkHsQTvs tvs) ctxt ty
-- mk_forall_ty makes a pure for-all type (no context)
mk_forall_ty :: HsExplicitFlag -> [LHsTyVarBndr name] -> LHsType name -> HsType name
-mk_forall_ty exp tvs (L _ (HsParTy ty)) = mk_forall_ty exp tvs ty
-mk_forall_ty exp1 tvs1 (L _ (HsForAllTy exp2 tvs2 ctxt ty)) = mkHsForAllTy (exp1 `plus` exp2) (tvs1 ++ tvs2) ctxt ty
-mk_forall_ty exp tvs ty = HsForAllTy exp tvs (noLoc []) ty
+mk_forall_ty exp tvs (L _ (HsParTy ty)) = mk_forall_ty exp tvs ty
+mk_forall_ty exp1 tvs1 (L _ (HsForAllTy exp2 qtvs2 ctxt ty)) = mkHsForAllTy (exp1 `plus` exp2) (tvs1 ++ hsq_tvs qtvs2) ctxt ty
+mk_forall_ty exp tvs ty = HsForAllTy exp (mkHsQTvs tvs) (noLoc []) ty
-- Even if tvs is empty, we still make a HsForAll!
-- In the Implicit case, this signals the place to do implicit quantification
-- In the Explicit case, it prevents implicit quantification
@@ -396,14 +409,14 @@ hsLTyVarName = hsTyVarName . unLoc
hsTyVarNames :: [HsTyVarBndr name] -> [name]
hsTyVarNames tvs = map hsTyVarName tvs
-hsLTyVarNames :: [LHsTyVarBndr name] -> [name]
-hsLTyVarNames = map hsLTyVarName
+hsLTyVarNames :: LHsTyVarBndrs name -> [name]
+hsLTyVarNames qtvs = map hsLTyVarName (hsQTvBndrs qtvs)
hsLTyVarLocName :: LHsTyVarBndr name -> Located name
hsLTyVarLocName = fmap hsTyVarName
-hsLTyVarLocNames :: [LHsTyVarBndr name] -> [Located name]
-hsLTyVarLocNames = map hsLTyVarLocName
+hsLTyVarLocNames :: LHsTyVarBndrs name -> [Located name]
+hsLTyVarLocNames qtvs = map hsLTyVarLocName (hsQTvBndrs qtvs)
\end{code}
@@ -421,31 +434,23 @@ mkHsAppTys fun_ty (arg_ty:arg_tys)
-- Add noLocs for inner nodes of the application;
-- they are never used
-splitHsInstDeclTy_maybe :: HsType name
- -> Maybe ([LHsTyVarBndr name], HsContext name, name, [LHsType name])
-splitHsInstDeclTy_maybe ty
- = fmap (\(tvs, cxt, L _ n, tys) -> (tvs, cxt, n, tys)) $ splitLHsInstDeclTy_maybe (noLoc ty)
-
splitLHsInstDeclTy_maybe
:: LHsType name
- -> Maybe ([LHsTyVarBndr name], HsContext name, Located name, [LHsType name])
+ -> Maybe (LHsTyVarBndrs name, HsContext name, Located name, [LHsType name])
-- Split up an instance decl type, returning the pieces
splitLHsInstDeclTy_maybe inst_ty = do
let (tvs, cxt, ty) = splitLHsForAllTy inst_ty
(cls, tys) <- splitLHsClassTy_maybe ty
return (tvs, cxt, cls, tys)
-splitHsForAllTy :: HsType name -> ([LHsTyVarBndr name], HsContext name, HsType name)
-splitHsForAllTy ty = case splitLHsForAllTy (noLoc ty) of (tvs, cxt, L _ ty) -> (tvs, cxt, ty)
-
splitLHsForAllTy
:: LHsType name
- -> ([LHsTyVarBndr name], HsContext name, LHsType name)
+ -> (LHsTyVarBndrs name, HsContext name, LHsType name)
splitLHsForAllTy poly_ty
= case unLoc poly_ty of
HsParTy ty -> splitLHsForAllTy ty
HsForAllTy _ tvs cxt ty -> (tvs, unLoc cxt, ty)
- _ -> ([], [], poly_ty)
+ _ -> (mkHsQTvs [], [], poly_ty)
-- The type vars should have been computed by now, even if they were implicit
splitHsClassTy_maybe :: HsType name -> Maybe (name, [LHsType name])
@@ -494,22 +499,25 @@ instance (OutputableBndr name) => Outputable (HsType name) where
instance Outputable HsTyLit where
ppr = ppr_tylit
-instance (Outputable sig) => Outputable (HsBndrSig sig) where
- ppr (HsBSig ty _) = ppr ty
+instance (OutputableBndr name) => Outputable (LHsTyVarBndrs name) where
+ ppr qtvs = interppSP (hsQTvBndrs qtvs)
instance (OutputableBndr name) => Outputable (HsTyVarBndr name) where
ppr (UserTyVar name) = ppr name
ppr (KindedTyVar name kind) = parens $ hsep [ppr name, dcolon, ppr kind]
-pprHsForAll :: OutputableBndr name => HsExplicitFlag -> [LHsTyVarBndr name] -> LHsContext name -> SDoc
-pprHsForAll exp tvs cxt
+instance (Outputable thing) => Outputable (HsWithBndrs thing) where
+ ppr (HsWB { hswb_cts = ty }) = ppr ty
+
+pprHsForAll :: OutputableBndr name => HsExplicitFlag -> LHsTyVarBndrs name -> LHsContext name -> SDoc
+pprHsForAll exp qtvs cxt
| show_forall = forall_part <+> pprHsContext (unLoc cxt)
| otherwise = pprHsContext (unLoc cxt)
where
show_forall = opt_PprStyle_Debug
- || (not (null tvs) && is_explicit)
+ || (not (null (hsQTvBndrs qtvs)) && is_explicit)
is_explicit = case exp of {Explicit -> True; Implicit -> False}
- forall_part = ptext (sLit "forall") <+> interppSP tvs <> dot
+ forall_part = ptext (sLit "forall") <+> ppr qtvs <> dot
pprHsContext :: (OutputableBndr name) => HsContext name -> SDoc
pprHsContext [] = empty
diff --git a/compiler/hsSyn/HsUtils.lhs b/compiler/hsSyn/HsUtils.lhs
index 8ac04761fe..32fe487609 100644
--- a/compiler/hsSyn/HsUtils.lhs
+++ b/compiler/hsSyn/HsUtils.lhs
@@ -33,7 +33,7 @@ module HsUtils(
nlHsTyApp, nlHsVar, nlHsLit, nlHsApp, nlHsApps, nlHsIntLit, nlHsVarApps,
nlHsDo, nlHsOpApp, nlHsLam, nlHsPar, nlHsIf, nlHsCase, nlList,
- mkLHsTupleExpr, mkLHsVarTuple, missingTupArg, mkHsBSig,
+ mkLHsTupleExpr, mkLHsVarTuple, missingTupArg,
-- Bindings
mkFunBind, mkVarBind, mkHsVarBind, mk_easy_FunBind, mkTopFunBind,
@@ -265,9 +265,6 @@ unqualQuasiQuote = mkRdrUnqual (mkVarOccFS (fsLit "quasiquote"))
mkHsString :: String -> HsLit
mkHsString s = HsString (mkFastString s)
-mkHsBSig :: a -> HsBndrSig a
-mkHsBSig x = HsBSig x (placeHolderBndrs, placeHolderBndrs)
-
-------------
userHsTyVarBndrs :: SrcSpan -> [name] -> [Located (HsTyVarBndr name)]
-- Caller sets location
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index a497dedcda..c26efb2597 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -38,6 +38,7 @@ module DynFlags (
GhcMode(..), isOneShot,
GhcLink(..), isNoLink,
PackageFlag(..),
+ PkgConfRef(..),
Option(..), showOpt,
DynLibLoader(..),
fFlags, fWarningFlags, fLangFlags, xFlags,
@@ -275,7 +276,6 @@ data DynFlag
| Opt_ForceRecomp
| Opt_ExcessPrecision
| Opt_EagerBlackHoling
- | Opt_ReadUserPackageConf
| Opt_NoHsMain
| Opt_SplitObjs
| Opt_StgStats
@@ -548,8 +548,8 @@ data DynFlags = DynFlags {
depSuffixes :: [String],
-- Package flags
- extraPkgConfs :: [FilePath],
- -- ^ The @-package-conf@ flags given on the command line, in the order
+ extraPkgConfs :: [PkgConfRef] -> [PkgConfRef],
+ -- ^ The @-package-db@ flags given on the command line, in the order
-- they appeared.
packageFlags :: [PackageFlag],
@@ -923,7 +923,7 @@ defaultDynFlags mySettings =
hpcDir = ".hpc",
- extraPkgConfs = [],
+ extraPkgConfs = id,
packageFlags = [],
pkgDatabase = Nothing,
pkgState = panic "no package state yet: call GHC.setSessionDynFlags",
@@ -1340,7 +1340,7 @@ parseDynamicFlagsCmdLine :: Monad m =>
parseDynamicFlagsCmdLine dflags args = parseDynamicFlags dflags args True
-- | Like 'parseDynamicFlagsCmdLine' but does not allow the package flags
--- (-package, -hide-package, -ignore-package, -hide-all-packages, -package-conf).
+-- (-package, -hide-package, -ignore-package, -hide-all-packages, -package-db).
-- Used to parse flags set in a modules pragma.
parseDynamicFilePragma :: Monad m =>
DynFlags -> [Located String]
@@ -1755,8 +1755,13 @@ dynamic_flags = [
package_flags :: [Flag (CmdLineP DynFlags)]
package_flags = [
------- Packages ----------------------------------------------------
- Flag "package-conf" (HasArg extraPkgConf_)
- , Flag "no-user-package-conf" (NoArg (unSetDynFlag Opt_ReadUserPackageConf))
+ Flag "package-db" (HasArg (addPkgConfRef . PkgConfFile))
+ , Flag "clear-package-db" (NoArg clearPkgConf)
+ , Flag "no-global-package-db" (NoArg removeGlobalPkgConf)
+ , Flag "no-user-package-db" (NoArg removeUserPkgConf)
+ , Flag "global-package-db" (NoArg (addPkgConfRef GlobalPkgConf))
+ , Flag "user-package-db" (NoArg (addPkgConfRef UserPkgConf))
+
, Flag "package-name" (hasArg setPackageName)
, Flag "package-id" (HasArg exposePackageId)
, Flag "package" (HasArg exposePackage)
@@ -2066,7 +2071,6 @@ xFlags = [
defaultFlags :: [DynFlag]
defaultFlags
= [ Opt_AutoLinkPackages,
- Opt_ReadUserPackageConf,
Opt_SharedImplib,
@@ -2404,8 +2408,28 @@ setVerbosity mb_n = upd (\dfs -> dfs{ verbosity = mb_n `orElse` 3 })
addCmdlineHCInclude :: String -> DynP ()
addCmdlineHCInclude a = upd (\s -> s{cmdlineHcIncludes = a : cmdlineHcIncludes s})
-extraPkgConf_ :: FilePath -> DynP ()
-extraPkgConf_ p = upd (\s -> s{ extraPkgConfs = p : extraPkgConfs s })
+data PkgConfRef
+ = GlobalPkgConf
+ | UserPkgConf
+ | PkgConfFile FilePath
+
+addPkgConfRef :: PkgConfRef -> DynP ()
+addPkgConfRef p = upd $ \s -> s { extraPkgConfs = (p:) . extraPkgConfs s }
+
+removeUserPkgConf :: DynP ()
+removeUserPkgConf = upd $ \s -> s { extraPkgConfs = filter isNotUser . extraPkgConfs s }
+ where
+ isNotUser UserPkgConf = False
+ isNotUser _ = True
+
+removeGlobalPkgConf :: DynP ()
+removeGlobalPkgConf = upd $ \s -> s { extraPkgConfs = filter isNotGlobal . extraPkgConfs s }
+ where
+ isNotGlobal GlobalPkgConf = False
+ isNotGlobal _ = True
+
+clearPkgConf :: DynP ()
+clearPkgConf = upd $ \s -> s { extraPkgConfs = const [] }
exposePackage, exposePackageId, hidePackage, ignorePackage,
trustPackage, distrustPackage :: String -> DynP ()
diff --git a/compiler/main/HscMain.hs b/compiler/main/HscMain.hs
index b975a20fd1..4a54c89545 100644
--- a/compiler/main/HscMain.hs
+++ b/compiler/main/HscMain.hs
@@ -1403,7 +1403,7 @@ IO monad as explained in Note [Interactively-bound Ids in GHCi] in TcRnDriver
--
-- We return Nothing to indicate an empty statement (or comment only), not a
-- parse error.
-hscStmt :: HscEnv -> String -> IO (Maybe ([Id], IO [HValue]))
+hscStmt :: HscEnv -> String -> IO (Maybe ([Id], IO [HValue], FixityEnv))
hscStmt hsc_env stmt = hscStmtWithLocation hsc_env stmt "<interactive>" 1
-- | Compile a stmt all the way to an HValue, but don't run it
@@ -1414,7 +1414,7 @@ hscStmtWithLocation :: HscEnv
-> String -- ^ The statement
-> String -- ^ The source
-> Int -- ^ Starting line
- -> IO (Maybe ([Id], IO [HValue]))
+ -> IO (Maybe ([Id], IO [HValue], FixityEnv))
hscStmtWithLocation hsc_env0 stmt source linenumber =
runInteractiveHsc hsc_env0 $ do
hsc_env <- getHscEnv
@@ -1431,7 +1431,7 @@ hscStmtWithLocation hsc_env0 stmt source linenumber =
-- Rename and typecheck it
-- Here we lift the stmt into the IO monad, see Note
-- [Interactively-bound Ids in GHCi] in TcRnDriver
- (ids, tc_expr) <- ioMsgMaybe $ tcRnStmt hsc_env icntxt parsed_stmt
+ (ids, tc_expr, fix_env) <- ioMsgMaybe $ tcRnStmt hsc_env icntxt parsed_stmt
-- Desugar it
ds_expr <- ioMsgMaybe $
@@ -1443,7 +1443,7 @@ hscStmtWithLocation hsc_env0 stmt source linenumber =
hval <- liftIO $ hscCompileCoreExpr hsc_env src_span ds_expr
let hval_io = unsafeCoerce# hval :: IO [HValue]
- return $ Just (ids, hval_io)
+ return $ Just (ids, hval_io, fix_env)
-- | Compile a decls
hscDecls :: HscEnv
diff --git a/compiler/main/HscTypes.lhs b/compiler/main/HscTypes.lhs
index 82712e2741..1c8276db33 100644
--- a/compiler/main/HscTypes.lhs
+++ b/compiler/main/HscTypes.lhs
@@ -942,6 +942,9 @@ data InteractiveContext
-- time we update the context, we just take the results
-- from the instance code that already does that.
+ ic_fix_env :: FixityEnv,
+ -- ^ Fixities declared in let statements
+
#ifdef GHCI
ic_resume :: [Resume],
-- ^ The stack of breakpoint contexts
@@ -983,6 +986,7 @@ emptyInteractiveContext dflags
ic_tythings = [],
ic_sys_vars = [],
ic_instances = ([],[]),
+ ic_fix_env = emptyNameEnv,
#ifdef GHCI
ic_resume = [],
#endif
diff --git a/compiler/main/InteractiveEval.hs b/compiler/main/InteractiveEval.hs
index a666220a6e..42147dce94 100644
--- a/compiler/main/InteractiveEval.hs
+++ b/compiler/main/InteractiveEval.hs
@@ -176,6 +176,12 @@ findEnclosingDecls hsc_env inf =
mb = getModBreaks hmi
in modBreaks_decls mb ! breakInfo_number inf
+-- | Update fixity environment in the current interactive context.
+updateFixityEnv :: GhcMonad m => FixityEnv -> m ()
+updateFixityEnv fix_env = do
+ hsc_env <- getSession
+ let ic = hsc_IC hsc_env
+ setSession $ hsc_env { hsc_IC = ic { ic_fix_env = fix_env } }
-- | Run a statement in the current interactive context. Statement
-- may bind multple values.
@@ -206,7 +212,9 @@ runStmtWithLocation source linenumber expr step =
-- empty statement / comment
Nothing -> return (RunOk [])
- Just (tyThings, hval) -> do
+ Just (tyThings, hval, fix_env) -> do
+ updateFixityEnv fix_env
+
status <-
withVirtualCWD $
withBreakAction (isStep step) idflags' breakMVar statusMVar $ do
@@ -947,7 +955,8 @@ typeKind normalise str = withSession $ \hsc_env -> do
compileExpr :: GhcMonad m => String -> m HValue
compileExpr expr = withSession $ \hsc_env -> do
- Just (ids, hval) <- liftIO $ hscStmt hsc_env ("let __cmCompileExpr = "++expr)
+ Just (ids, hval, fix_env) <- liftIO $ hscStmt hsc_env ("let __cmCompileExpr = "++expr)
+ updateFixityEnv fix_env
hvals <- liftIO hval
case (ids,hvals) of
([_],[hv]) -> return hv
@@ -971,9 +980,11 @@ dynCompileExpr expr = do
}
setContext (IIDecl importDecl : iis)
let stmt = "let __dynCompileExpr = Data.Dynamic.toDyn (" ++ expr ++ ")"
- Just (ids, hvals) <- withSession $ \hsc_env ->
+ Just (ids, hvals, fix_env) <- withSession $ \hsc_env ->
liftIO $ hscStmt hsc_env stmt
setContext iis
+ updateFixityEnv fix_env
+
vals <- liftIO (unsafeCoerce# hvals :: IO [Dynamic])
case (ids,vals) of
(_:[], v:[]) -> return v
diff --git a/compiler/main/Packages.lhs b/compiler/main/Packages.lhs
index aa5a432762..cdda96193c 100644
--- a/compiler/main/Packages.lhs
+++ b/compiler/main/Packages.lhs
@@ -152,10 +152,10 @@ getPackageDetails :: PackageState -> PackageId -> PackageConfig
getPackageDetails ps pid = expectJust "getPackageDetails" (lookupPackage (pkgIdMap ps) pid)
-- ----------------------------------------------------------------------------
--- Loading the package config files and building up the package state
+-- Loading the package db files and building up the package state
-- | Call this after 'DynFlags.parseDynFlags'. It reads the package
--- configuration files, and sets up various internal tables of package
+-- database files, and sets up various internal tables of package
-- information, according to the package-related flags on the
-- command-line (@-package@, @-hide-package@ etc.)
--
@@ -184,46 +184,37 @@ initPackages dflags = do
readPackageConfigs :: DynFlags -> IO [PackageConfig]
readPackageConfigs dflags = do
- e_pkg_path <- tryIO (getEnv "GHC_PACKAGE_PATH")
- system_pkgconfs <- getSystemPackageConfigs dflags
-
- let pkgconfs = case e_pkg_path of
- Left _ -> system_pkgconfs
- Right path
- | last cs == "" -> init cs ++ system_pkgconfs
- | otherwise -> cs
- where cs = parseSearchPath path
- -- if the path ends in a separator (eg. "/foo/bar:")
- -- the we tack on the system paths.
-
- pkgs <- mapM (readPackageConfig dflags)
- (pkgconfs ++ reverse (extraPkgConfs dflags))
- -- later packages shadow earlier ones. extraPkgConfs
- -- is in the opposite order to the flags on the
- -- command line.
-
- return (concat pkgs)
-
-
-getSystemPackageConfigs :: DynFlags -> IO [FilePath]
-getSystemPackageConfigs dflags = do
- -- System one always comes first
- let system_pkgconf = systemPackageConfig dflags
-
- -- Read user's package conf (eg. ~/.ghc/i386-linux-6.3/package.conf)
- -- unless the -no-user-package-conf flag was given.
- user_pkgconf <- do
- if not (dopt Opt_ReadUserPackageConf dflags) then return [] else do
- appdir <- getAppUserDataDirectory "ghc"
- let
- dir = appdir </> (TARGET_ARCH ++ '-':TARGET_OS ++ '-':cProjectVersion)
- pkgconf = dir </> "package.conf.d"
- --
- exist <- doesDirectoryExist pkgconf
- if exist then return [pkgconf] else return []
- `catchIO` (\_ -> return [])
-
- return (system_pkgconf : user_pkgconf)
+ let system_conf_refs = [UserPkgConf, GlobalPkgConf]
+
+ e_pkg_path <- tryIO (getEnv "GHC_PACKAGE_PATH")
+ let base_conf_refs = case e_pkg_path of
+ Left _ -> system_conf_refs
+ Right path
+ | null (last cs)
+ -> map PkgConfFile (init cs) ++ system_conf_refs
+ | otherwise
+ -> map PkgConfFile cs
+ where cs = parseSearchPath path
+ -- if the path ends in a separator (eg. "/foo/bar:")
+ -- then we tack on the system paths.
+
+ let conf_refs = reverse (extraPkgConfs dflags base_conf_refs)
+ -- later packages shadow earlier ones. extraPkgConfs
+ -- is in the opposite order to the flags on the
+ -- command line.
+ confs <- liftM catMaybes $ mapM (resolvePackageConfig dflags) conf_refs
+
+ liftM concat $ mapM (readPackageConfig dflags) confs
+
+resolvePackageConfig :: DynFlags -> PkgConfRef -> IO (Maybe FilePath)
+resolvePackageConfig dflags GlobalPkgConf = return $ Just (systemPackageConfig dflags)
+resolvePackageConfig _ UserPkgConf = handleIO (\_ -> return Nothing) $ do
+ appdir <- getAppUserDataDirectory "ghc"
+ let dir = appdir </> (TARGET_ARCH ++ '-':TARGET_OS ++ '-':cProjectVersion)
+ pkgconf = dir </> "package.conf.d"
+ exist <- doesDirectoryExist pkgconf
+ return $ if exist then Just pkgconf else Nothing
+resolvePackageConfig _ (PkgConfFile name) = return $ Just name
readPackageConfig :: DynFlags -> FilePath -> IO [PackageConfig]
readPackageConfig dflags conf_file = do
diff --git a/compiler/parser/Lexer.x b/compiler/parser/Lexer.x
index 378a25c8e1..e40f7b2f11 100644
--- a/compiler/parser/Lexer.x
+++ b/compiler/parser/Lexer.x
@@ -766,13 +766,17 @@ pop_and act span buf len = do _ <- popLexState
nextCharIs :: StringBuffer -> (Char -> Bool) -> Bool
nextCharIs buf p = not (atEnd buf) && p (currentChar buf)
+{-# INLINE nextCharIsNot #-}
+nextCharIsNot :: StringBuffer -> (Char -> Bool) -> Bool
+nextCharIsNot buf p = not (nextCharIs buf p)
+
notFollowedBy :: Char -> AlexAccPred Int
notFollowedBy char _ _ _ (AI _ buf)
- = nextCharIs buf (/=char)
+ = nextCharIsNot buf (== char)
notFollowedBySymbol :: AlexAccPred Int
notFollowedBySymbol _ _ _ (AI _ buf)
- = nextCharIs buf (`notElem` "!#$%&*+./<=>?@\\^|-~")
+ = nextCharIsNot buf (`elem` "!#$%&*+./<=>?@\\^|-~")
-- We must reject doc comments as being ordinary comments everywhere.
-- In some cases the doc comment will be selected as the lexeme due to
@@ -782,13 +786,16 @@ notFollowedBySymbol _ _ _ (AI _ buf)
isNormalComment :: AlexAccPred Int
isNormalComment bits _ _ (AI _ buf)
| haddockEnabled bits = notFollowedByDocOrPragma
- | otherwise = nextCharIs buf (/='#')
+ | otherwise = nextCharIsNot buf (== '#')
where
notFollowedByDocOrPragma
- = not $ spaceAndP buf (`nextCharIs` (`elem` "|^*$#"))
+ = afterOptionalSpace buf (\b -> nextCharIsNot b (`elem` "|^*$#"))
-spaceAndP :: StringBuffer -> (StringBuffer -> Bool) -> Bool
-spaceAndP buf p = p buf || nextCharIs buf (==' ') && p (snd (nextChar buf))
+afterOptionalSpace :: StringBuffer -> (StringBuffer -> Bool) -> Bool
+afterOptionalSpace buf p
+ = if nextCharIs buf (== ' ')
+ then p (snd (nextChar buf))
+ else p buf
atEOL :: AlexAccPred Int
atEOL _ _ _ (AI _ buf) = atEnd buf || currentChar buf == '\n'
@@ -2341,7 +2348,7 @@ dispatch_pragmas prags span buf len = case Map.lookup (clean_pragma (lexemeToStr
known_pragma :: Map String Action -> AlexAccPred Int
known_pragma prags _ _ len (AI _ buf) = (isJust $ Map.lookup (clean_pragma (lexemeToString (offsetBytes (- len) buf) len)) prags)
- && (nextCharIs buf (\c -> not (isAlphaNum c || c == '_')))
+ && (nextCharIsNot buf (\c -> isAlphaNum c || c == '_'))
clean_pragma :: String -> String
clean_pragma prag = canon_ws (map toLower (unprefix prag))
diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp
index a9cb1d34b7..759d5449f9 100644
--- a/compiler/parser/Parser.y.pp
+++ b/compiler/parser/Parser.y.pp
@@ -728,9 +728,9 @@ data_or_newtype :: { Located NewOrData }
: 'data' { L1 DataType }
| 'newtype' { L1 NewType }
-opt_kind_sig :: { Located (Maybe (HsBndrSig (LHsKind RdrName))) }
+opt_kind_sig :: { Located (Maybe (LHsKind RdrName)) }
: { noLoc Nothing }
- | '::' kind { LL (Just (mkHsBSig $2)) }
+ | '::' kind { LL (Just $2) }
-- tycl_hdr parses the header of a class or data type decl,
-- which takes the form
@@ -877,7 +877,7 @@ rule_var_list :: { [RuleBndr RdrName] }
rule_var :: { RuleBndr RdrName }
: varid { RuleBndr $1 }
- | '(' varid '::' ctype ')' { RuleBndrSig $2 (mkHsBSig $4) }
+ | '(' varid '::' ctype ')' { RuleBndrSig $2 (mkHsWithBndrs $4) }
-----------------------------------------------------------------------------
-- Warnings and deprecations (c.f. rules)
@@ -1113,7 +1113,7 @@ tv_bndrs :: { [LHsTyVarBndr RdrName] }
tv_bndr :: { LHsTyVarBndr RdrName }
: tyvar { L1 (UserTyVar (unLoc $1)) }
- | '(' tyvar '::' kind ')' { LL (KindedTyVar (unLoc $2) (mkHsBSig $4)) }
+ | '(' tyvar '::' kind ')' { LL (KindedTyVar (unLoc $2) $4) }
fds :: { Located [Located (FunDep RdrName)] }
: {- empty -} { noLoc [] }
diff --git a/compiler/parser/ParserCore.y b/compiler/parser/ParserCore.y
index eee8831065..0382fcae7d 100644
--- a/compiler/parser/ParserCore.y
+++ b/compiler/parser/ParserCore.y
@@ -128,14 +128,14 @@ tdefs :: { [TyClDecl RdrName] }
tdef :: { TyClDecl RdrName }
: '%data' q_tc_name tv_bndrs '=' '{' cons '}' ';'
{ TyDecl { tcdLName = noLoc (ifaceExtRdrName $2)
- , tcdTyVars = map toHsTvBndr $3
+ , tcdTyVars = mkHsQTvs (map toHsTvBndr $3)
, tcdTyDefn = TyData { td_ND = DataType, td_ctxt = noLoc []
, td_kindSig = Nothing
, td_cons = $6, td_derivs = Nothing } } }
| '%newtype' q_tc_name tv_bndrs trep ';'
{ let tc_rdr = ifaceExtRdrName $2 in
TyDecl { tcdLName = noLoc tc_rdr
- , tcdTyVars = map toHsTvBndr $3
+ , tcdTyVars = mkHsQTvs (map toHsTvBndr $3)
, tcdTyDefn = TyData { td_ND = NewType, td_ctxt = noLoc []
, td_kindSig = Nothing
, td_cons = $4 (rdrNameOcc tc_rdr), td_derivs = Nothing } } }
@@ -377,16 +377,16 @@ ifaceArrow ifT1 ifT2 = IfaceFunTy ifT1 ifT2
toHsTvBndr :: IfaceTvBndr -> LHsTyVarBndr RdrName
toHsTvBndr (tv,k) = noLoc $ KindedTyVar (mkRdrUnqual (mkTyVarOccFS tv)) bsig
where
- bsig = mkHsBSig (toHsKind k)
+ bsig = toHsKind k
ifaceExtRdrName :: Name -> RdrName
ifaceExtRdrName name = mkOrig (nameModule name) (nameOccName name)
ifaceExtRdrName other = pprPanic "ParserCore.ifaceExtRdrName" (ppr other)
add_forall tv (L _ (HsForAllTy exp tvs cxt t))
- = noLoc $ HsForAllTy exp (tv:tvs) cxt t
+ = noLoc $ HsForAllTy exp (mkHsQTvs (tv : hsQTvBndrs tvs)) cxt t
add_forall tv t
- = noLoc $ HsForAllTy Explicit [tv] (noLoc []) t
+ = noLoc $ HsForAllTy Explicit (mkHsQTvs [tv]) (noLoc []) t
happyError :: P a
happyError s l = failP (show l ++ ": Parse error\n") (take 100 s) l
diff --git a/compiler/parser/RdrHsSyn.lhs b/compiler/parser/RdrHsSyn.lhs
index 95b65de192..350aedb6f0 100644
--- a/compiler/parser/RdrHsSyn.lhs
+++ b/compiler/parser/RdrHsSyn.lhs
@@ -122,7 +122,7 @@ mkTyData :: SrcSpan
-> NewOrData
-> Maybe CType
-> Located (Maybe (LHsContext RdrName), LHsType RdrName)
- -> Maybe (HsBndrSig (LHsKind RdrName))
+ -> Maybe (LHsKind RdrName)
-> [LConDecl RdrName]
-> Maybe [LHsType RdrName]
-> P (LTyClDecl RdrName)
@@ -138,20 +138,20 @@ mkFamInstData :: SrcSpan
-> NewOrData
-> Maybe CType
-> Located (Maybe (LHsContext RdrName), LHsType RdrName)
- -> Maybe (HsBndrSig (LHsKind RdrName))
+ -> Maybe (LHsKind RdrName)
-> [LConDecl RdrName]
-> Maybe [LHsType RdrName]
-> P (LFamInstDecl RdrName)
mkFamInstData loc new_or_data cType (L _ (mcxt, tycl_hdr)) ksig data_cons maybe_deriv
= do { (tc, tparams) <- checkTyClHdr tycl_hdr
; defn <- mkDataDefn new_or_data cType mcxt ksig data_cons maybe_deriv
- ; return (L loc (FamInstDecl { fid_tycon = tc, fid_pats = mkHsBSig tparams
+ ; return (L loc (FamInstDecl { fid_tycon = tc, fid_pats = mkHsWithBndrs tparams
, fid_defn = defn, fid_fvs = placeHolderNames })) }
mkDataDefn :: NewOrData
-> Maybe CType
-> Maybe (LHsContext RdrName)
- -> Maybe (HsBndrSig (LHsKind RdrName))
+ -> Maybe (LHsKind RdrName)
-> [LConDecl RdrName]
-> Maybe [LHsType RdrName]
-> P (HsTyDefn RdrName)
@@ -181,14 +181,14 @@ mkFamInstSynonym :: SrcSpan
-> P (LFamInstDecl RdrName)
mkFamInstSynonym loc lhs rhs
= do { (tc, tparams) <- checkTyClHdr lhs
- ; return (L loc (FamInstDecl { fid_tycon = tc, fid_pats = mkHsBSig tparams
+ ; return (L loc (FamInstDecl { fid_tycon = tc, fid_pats = mkHsWithBndrs tparams
, fid_defn = TySynonym { td_synRhs = rhs }
, fid_fvs = placeHolderNames })) }
mkTyFamily :: SrcSpan
-> FamilyFlavour
-> LHsType RdrName -- LHS
- -> Maybe (HsBndrSig (LHsKind RdrName)) -- Optional kind signature
+ -> Maybe (LHsKind RdrName) -- Optional kind signature
-> P (LTyClDecl RdrName)
mkTyFamily loc flavour lhs ksig
= do { (tc, tparams) <- checkTyClHdr lhs
@@ -367,7 +367,7 @@ mkDeprecatedGadtRecordDecl loc (L con_loc con) flds res_ty
; return (L loc (ConDecl { con_old_rec = True
, con_name = data_con
, con_explicit = Implicit
- , con_qvars = []
+ , con_qvars = mkHsQTvs []
, con_cxt = noLoc []
, con_details = RecCon flds
, con_res = ResTyGADT res_ty
@@ -381,7 +381,7 @@ mkSimpleConDecl name qvars cxt details
= ConDecl { con_old_rec = False
, con_name = name
, con_explicit = Explicit
- , con_qvars = qvars
+ , con_qvars = mkHsQTvs qvars
, con_cxt = cxt
, con_details = details
, con_res = ResTyH98
@@ -444,17 +444,18 @@ we can bring x,y into scope. So:
* For RecCon we do not
\begin{code}
-checkTyVars :: LHsType RdrName -> [LHsType RdrName] -> P [LHsTyVarBndr RdrName]
+checkTyVars :: LHsType RdrName -> [LHsType RdrName] -> P (LHsTyVarBndrs RdrName)
-- Check whether the given list of type parameters are all type variables
-- (possibly with a kind signature). If the second argument is `False',
-- only type variables are allowed and we raise an error on encountering a
-- non-variable; otherwise, we allow non-variable arguments and return the
-- entire list of parameters.
-checkTyVars tycl_hdr tparms = mapM chk tparms
+checkTyVars tycl_hdr tparms = do { tvs <- mapM chk tparms
+ ; return (mkHsQTvs tvs) }
where
-- Check that the name space is correct!
chk (L l (HsKindSig (L _ (HsTyVar tv)) k))
- | isRdrTyVar tv = return (L l (KindedTyVar tv (mkHsBSig k)))
+ | isRdrTyVar tv = return (L l (KindedTyVar tv k))
chk (L l (HsTyVar tv))
| isRdrTyVar tv = return (L l (UserTyVar tv))
chk t@(L l _)
@@ -579,7 +580,7 @@ checkAPat dynflags loc e0 = case e0 of
let t' = case t of
L _ (HsForAllTy Implicit _ (L _ []) ty) -> ty
other -> other
- return (SigPatIn e (mkHsBSig t'))
+ return (SigPatIn e (mkHsWithBndrs t'))
-- n+k patterns
OpApp (L nloc (HsVar n)) (L _ (HsVar plus)) _
diff --git a/compiler/rename/RnBinds.lhs b/compiler/rename/RnBinds.lhs
index a8f882a48d..79ccb2179a 100644
--- a/compiler/rename/RnBinds.lhs
+++ b/compiler/rename/RnBinds.lhs
@@ -539,7 +539,7 @@ mkSigTvFn sigs
= \n -> lookupNameEnv env n `orElse` []
where
env :: NameEnv [Name]
- env = mkNameEnv [ (name, map hsLTyVarName ltvs)
+ env = mkNameEnv [ (name, hsLTyVarNames ltvs)
| L _ (TypeSig names
(L _ (HsForAllTy Explicit ltvs _ _))) <- sigs
, (L _ name) <- names]
diff --git a/compiler/rename/RnEnv.lhs b/compiler/rename/RnEnv.lhs
index 9cb04ff47f..b1f393baaf 100644
--- a/compiler/rename/RnEnv.lhs
+++ b/compiler/rename/RnEnv.lhs
@@ -36,7 +36,7 @@ module RnEnv (
bindLocatedLocalsFV, bindLocatedLocalsRn,
extendTyVarEnvFVRn,
- checkDupRdrNames, checkDupAndShadowedRdrNames,
+ checkDupRdrNames, checkShadowedRdrNames,
checkDupNames, checkDupAndShadowedNames,
addFvRn, mapFvRn, mapMaybeFvRn, mapFvRnCPS,
warnUnusedMatches,
@@ -1185,7 +1185,8 @@ bindLocatedLocalsRn :: [Located RdrName]
-> ([Name] -> RnM a)
-> RnM a
bindLocatedLocalsRn rdr_names_w_loc enclosed_scope
- = do { checkDupAndShadowedRdrNames rdr_names_w_loc
+ = do { checkDupRdrNames rdr_names_w_loc
+ ; checkShadowedRdrNames rdr_names_w_loc
-- Make fresh Names and extend the environment
; names <- newLocalBndrsRn rdr_names_w_loc
@@ -1243,11 +1244,10 @@ checkDupNames names
-- See Note [Binders in Template Haskell] in Convert
---------------------
-checkDupAndShadowedRdrNames :: [Located RdrName] -> RnM ()
-checkDupAndShadowedRdrNames loc_rdr_names
- = do { checkDupRdrNames loc_rdr_names
- ; envs <- getRdrEnvs
- ; checkShadowedOccs envs loc_occs }
+checkShadowedRdrNames :: [Located RdrName] -> RnM ()
+checkShadowedRdrNames loc_rdr_names
+ = do { envs <- getRdrEnvs
+ ; checkShadowedOccs envs loc_occs }
where
loc_occs = [(loc,rdrNameOcc rdr) | L loc rdr <- loc_rdr_names]
@@ -1645,8 +1645,10 @@ data HsDocContext
| SpliceTypeCtx (LHsType RdrName)
| ClassInstanceCtx
| VectDeclCtx (Located RdrName)
+ | GenericCtx SDoc -- Maybe we want to use this more!
docOfHsDocContext :: HsDocContext -> SDoc
+docOfHsDocContext (GenericCtx doc) = doc
docOfHsDocContext (TypeSigCtx doc) = text "In the type signature for" <+> doc
docOfHsDocContext PatCtx = text "In a pattern type-signature"
docOfHsDocContext SpecInstSigCtx = text "In a SPECIALISE instance pragma"
@@ -1666,5 +1668,4 @@ docOfHsDocContext GHCiCtx = ptext (sLit "In GHCi input")
docOfHsDocContext (SpliceTypeCtx hs_ty) = ptext (sLit "In the spliced type") <+> ppr hs_ty
docOfHsDocContext ClassInstanceCtx = ptext (sLit "TcSplice.reifyInstances")
docOfHsDocContext (VectDeclCtx tycon) = ptext (sLit "In the VECTORISE pragma for type constructor") <+> quotes (ppr tycon)
-
\end{code}
diff --git a/compiler/rename/RnPat.lhs b/compiler/rename/RnPat.lhs
index d0302a19a2..3e3c2b66d2 100644
--- a/compiler/rename/RnPat.lhs
+++ b/compiler/rename/RnPat.lhs
@@ -162,9 +162,9 @@ matchNameMaker ctxt = LamMk report_unused
StmtCtxt GhciStmt -> False
_ -> True
-rnHsSigCps :: HsBndrSig (LHsType RdrName) -> CpsRn (HsBndrSig (LHsType Name))
+rnHsSigCps :: HsWithBndrs (LHsType RdrName) -> CpsRn (HsWithBndrs (LHsType Name))
rnHsSigCps sig
- = CpsRn (rnHsBndrSig True PatCtx sig)
+ = CpsRn (rnHsBndrSig PatCtx sig)
newPatName :: NameMaker -> Located RdrName -> CpsRn Name
newPatName (LamMk report_unused) rdr_name
diff --git a/compiler/rename/RnSource.lhs b/compiler/rename/RnSource.lhs
index 8c338c810a..9509b0a4b2 100644
--- a/compiler/rename/RnSource.lhs
+++ b/compiler/rename/RnSource.lhs
@@ -43,7 +43,6 @@ import Outputable
import Bag
import BasicTypes ( RuleName )
import FastString
-import Util ( filterOut )
import SrcLoc
import DynFlags
import HscTypes ( HscEnv, hsc_dflags )
@@ -485,7 +484,9 @@ rnSrcInstDecl (ClsInstD { cid_poly_ty = inst_ty, cid_binds = mbinds
-- to remove the context).
rnFamInstDecl :: Maybe (Name, [Name]) -> FamInstDecl RdrName -> RnM (FamInstDecl Name, FreeVars)
-rnFamInstDecl mb_cls (FamInstDecl { fid_tycon = tycon, fid_pats = HsBSig pats _, fid_defn = defn })
+rnFamInstDecl mb_cls (FamInstDecl { fid_tycon = tycon
+ , fid_pats = HsWB { hswb_cts = pats }
+ , fid_defn = defn })
= do { tycon' <- lookupFamInstName (fmap fst mb_cls) tycon
; let loc = case pats of
[] -> pprPanic "rnFamInstDecl" (ppr tycon)
@@ -494,8 +495,9 @@ rnFamInstDecl mb_cls (FamInstDecl { fid_tycon = tycon, fid_pats = HsBSig pats _,
(kv_rdr_names, tv_rdr_names) = extractHsTysRdrTyVars pats
- ; kv_names <- mkTyVarBndrNames mb_cls (map (L loc) kv_rdr_names)
- ; tv_names <- mkTyVarBndrNames mb_cls (map (L loc) tv_rdr_names)
+ ; rdr_env <- getLocalRdrEnv
+ ; kv_names <- mapM (newTyVarNameRn mb_cls rdr_env loc) kv_rdr_names
+ ; tv_names <- mapM (newTyVarNameRn mb_cls rdr_env loc) tv_rdr_names
-- All the free vars of the family patterns
-- with a sensible binding location
; ((pats', defn'), fvs)
@@ -516,8 +518,8 @@ rnFamInstDecl mb_cls (FamInstDecl { fid_tycon = tycon, fid_pats = HsBSig pats _,
; let all_fvs = fvs `addOneFV` unLoc tycon'
; return ( FamInstDecl { fid_tycon = tycon'
- , fid_pats = HsBSig pats' (kv_names, tv_names)
- , fid_defn = defn', fid_fvs = all_fvs }
+ , fid_pats = HsWB { hswb_cts = pats', hswb_kvs = kv_names, hswb_tvs = tv_names }
+ , fid_defn = defn', fid_fvs = all_fvs }
, all_fvs ) }
-- type instance => use, hence addOneFV
\end{code}
@@ -543,13 +545,13 @@ For the method bindings in class and instance decls, we extend the
type variable environment iff -fglasgow-exts
\begin{code}
-extendTyVarEnvForMethodBinds :: [LHsTyVarBndr Name]
+extendTyVarEnvForMethodBinds :: LHsTyVarBndrs Name
-> RnM (Bag (LHsBind Name), FreeVars)
-> RnM (Bag (LHsBind Name), FreeVars)
extendTyVarEnvForMethodBinds tyvars thing_inside
= do { scoped_tvs <- xoptM Opt_ScopedTypeVariables
; if scoped_tvs then
- extendTyVarEnvFVRn (map hsLTyVarName tyvars) thing_inside
+ extendTyVarEnvFVRn (hsLTyVarNames tyvars) thing_inside
else
thing_inside }
\end{code}
@@ -584,7 +586,8 @@ standaloneDerivErr
rnHsRuleDecl :: RuleDecl RdrName -> RnM (RuleDecl Name, FreeVars)
rnHsRuleDecl (HsRule rule_name act vars lhs _fv_lhs rhs _fv_rhs)
= do { let rdr_names_w_loc = map get_var vars
- ; checkDupAndShadowedRdrNames rdr_names_w_loc
+ ; checkDupRdrNames rdr_names_w_loc
+ ; checkShadowedRdrNames rdr_names_w_loc
; names <- newLocalBndrsRn rdr_names_w_loc
; bindHsRuleVars rule_name vars names $ \ vars' ->
do { (lhs', fv_lhs') <- rnLExpr lhs
@@ -610,7 +613,7 @@ bindHsRuleVars rule_name vars names thing_inside
thing_inside (RuleBndr (L loc n) : vars')
go (RuleBndrSig (L loc _) bsig : vars) (n : ns) thing_inside
- = rnHsBndrSig True doc bsig $ \ bsig' ->
+ = rnHsBndrSig doc bsig $ \ bsig' ->
go vars ns $ \ vars' ->
thing_inside (RuleBndrSig (L loc n) bsig' : vars')
@@ -841,38 +844,40 @@ rnTyClDecl _ (ForeignType {tcdLName = name, tcdExtName = ext_name})
-- in a class decl
rnTyClDecl mb_cls (TyFamily { tcdLName = tycon, tcdTyVars = tyvars
, tcdFlavour = flav, tcdKindSig = kind })
- = do { let tv_rdr_names = hsLTyVarLocNames tyvars
- ; checkDupRdrNames tv_rdr_names -- Check for duplicated bindings
- ; tv_names <- mkTyVarBndrNames mb_cls tv_rdr_names
- ; bindTyVarsRn fmly_doc tyvars tv_names $ \tyvars' ->
+ = bindHsTyVars fmly_doc mb_cls kvs tyvars $ \tyvars' ->
do { tycon' <- lookupLocatedTopBndrRn tycon
; (kind', fv_kind) <- rnLHsMaybeKind fmly_doc kind
; return ( TyFamily { tcdLName = tycon', tcdTyVars = tyvars'
, tcdFlavour = flav, tcdKindSig = kind' }
- , fv_kind) } }
+ , fv_kind ) }
where
fmly_doc = TyFamilyCtx tycon
+ kvs = extractRdrKindSigVars kind
-- "data", "newtype" declarations
-- both top level and (for an associated type) in an instance decl
-rnTyClDecl _ (TyDecl { tcdLName = tycon, tcdTyVars = tyvars, tcdTyDefn = defn })
+rnTyClDecl mb_cls (TyDecl { tcdLName = tycon, tcdTyVars = tyvars, tcdTyDefn = defn })
= do { tycon' <- lookupLocatedTopBndrRn tycon
- ; ((tyvars', defn'), fvs) <- bindHsTyVars (TyDataCtx tycon) tyvars $ \ tyvars' ->
+ ; let kvs = extractTyDefnKindVars defn
+ ; traceRn (text "rntycl-ty" <+> ppr tycon <+> ppr kvs)
+ ; ((tyvars', defn'), fvs) <- bindHsTyVars (TyDataCtx tycon) mb_cls kvs tyvars $ \ tyvars' ->
do { (defn', fvs) <- rnTyDefn tycon defn
; return ((tyvars', defn'), fvs) }
; return (TyDecl { tcdLName = tycon', tcdTyVars = tyvars'
, tcdTyDefn = defn', tcdFVs = fvs }, fvs) }
-rnTyClDecl _ (ClassDecl {tcdCtxt = context, tcdLName = lcls,
- tcdTyVars = tyvars, tcdFDs = fds, tcdSigs = sigs,
- tcdMeths = mbinds, tcdATs = ats, tcdATDefs = at_defs,
- tcdDocs = docs})
+rnTyClDecl mb_cls (ClassDecl {tcdCtxt = context, tcdLName = lcls,
+ tcdTyVars = tyvars, tcdFDs = fds, tcdSigs = sigs,
+ tcdMeths = mbinds, tcdATs = ats, tcdATDefs = at_defs,
+ tcdDocs = docs})
= do { lcls' <- lookupLocatedTopBndrRn lcls
; let cls' = unLoc lcls'
+ kvs = [] -- No scoped kind vars except those in
+ -- kind signatures on the tyvars
-- Tyvars scope over superclass context and method signatures
; ((tyvars', context', fds', ats', at_defs', sigs'), stuff_fvs)
- <- bindHsTyVars cls_doc tyvars $ \ tyvars' -> do
+ <- bindHsTyVars cls_doc mb_cls kvs tyvars $ \ tyvars' -> do
-- Checks for distinct tyvars
{ (context', cxt_fvs) <- rnContext cls_doc context
; fds' <- rnFds (docOfHsDocContext cls_doc) fds
@@ -1043,21 +1048,6 @@ is jolly confusing. See Trac #4875
\begin{code}
---------------
-mkTyVarBndrNames :: Maybe a -> [Located RdrName] -> RnM [Name]
-mkTyVarBndrNames Nothing tv_rdr_names
- = newLocalBndrsRn tv_rdr_names
-mkTyVarBndrNames (Just _) tv_rdr_names
- = do { rdr_env <- getLocalRdrEnv
- ; let mk_tv_name :: Located RdrName -> RnM Name
- -- Use the same Name as the parent class decl
- mk_tv_name (L l tv_rdr)
- = case lookupLocalRdrEnv rdr_env tv_rdr of
- Just n -> return n
- Nothing -> newLocalBndrRn (L l tv_rdr)
-
- ; mapM mk_tv_name tv_rdr_names }
-
----------------
badAssocRhs :: [Name] -> RnM ()
badAssocRhs ns
= addErr (hang (ptext (sLit "The RHS of an associated type declaration mentions type variable")
@@ -1082,22 +1072,21 @@ rnConDecl decl@(ConDecl { con_name = name, con_qvars = tvs
-- For GADT syntax, the tvs are all the quantified tyvars
-- Hence the 'filter' in the ResTyH98 case only
; rdr_env <- getLocalRdrEnv
- ; let in_scope tv = tv `elemLocalRdrEnv` rdr_env
- arg_tys = hsConDeclArgTys details
- mentioned_tvs = case res_ty of
- ResTyH98 -> filterOut in_scope (get_rdr_tvs arg_tys)
- ResTyGADT ty -> get_rdr_tvs (ty : arg_tys)
+ ; let arg_tys = hsConDeclArgTys details
+ (free_kvs, free_tvs) = case res_ty of
+ ResTyH98 -> filterInScope rdr_env (get_rdr_tvs arg_tys)
+ ResTyGADT ty -> get_rdr_tvs (ty : arg_tys)
-- With an Explicit forall, check for unused binders
-- With Implicit, find the mentioned ones, and use them as binders
; new_tvs <- case expl of
- Implicit -> return (userHsTyVarBndrs loc mentioned_tvs)
- Explicit -> do { warnUnusedForAlls (docOfHsDocContext doc) tvs mentioned_tvs
+ Implicit -> return (mkHsQTvs (userHsTyVarBndrs loc free_tvs))
+ Explicit -> do { warnUnusedForAlls (docOfHsDocContext doc) tvs free_tvs
; return tvs }
; mb_doc' <- rnMbLHsDoc mb_doc
- ; bindHsTyVars doc new_tvs $ \new_tyvars -> do
+ ; bindHsTyVars doc Nothing free_kvs new_tvs $ \new_tyvars -> do
{ (new_context, fvs1) <- rnContext doc lcxt
; (new_details, fvs2) <- rnConDeclDetails doc details
; (new_details', new_res_ty, fvs3) <- rnConResult doc (unLoc new_name) new_details res_ty
@@ -1106,7 +1095,7 @@ rnConDecl decl@(ConDecl { con_name = name, con_qvars = tvs
fvs1 `plusFV` fvs2 `plusFV` fvs3) }}
where
doc = ConDeclCtx name
- get_rdr_tvs tys = snd (extractHsTysRdrTyVars (cxt ++ tys))
+ get_rdr_tvs tys = extractHsTysRdrTyVars (cxt ++ tys)
rnConResult :: HsDocContext -> Name
-> HsConDetails (LHsType Name) [ConDeclField Name]
diff --git a/compiler/rename/RnTypes.lhs b/compiler/rename/RnTypes.lhs
index 99401faefc..1b2e8417f3 100644
--- a/compiler/rename/RnTypes.lhs
+++ b/compiler/rename/RnTypes.lhs
@@ -16,7 +16,7 @@ module RnTypes (
rnHsType, rnLHsType, rnLHsTypes, rnContext,
rnHsKind, rnLHsKind, rnLHsMaybeKind,
rnHsSigType, rnLHsInstType, rnConDeclFields,
- rnIPName,
+ rnIPName, newTyVarNameRn,
-- Precence related stuff
mkOpAppRn, mkNegAppRn, mkOpFormRn, mkConOpPatRn,
@@ -26,9 +26,9 @@ module RnTypes (
rnSplice, checkTH,
-- Binding related stuff
- bindSigTyVarsFV, bindHsTyVars, bindTyVarsRn, rnHsBndrSig,
- extractHsTyRdrTyVars, extractHsTysRdrTyVars
-
+ bindSigTyVarsFV, bindHsTyVars, rnHsBndrSig,
+ extractHsTyRdrTyVars, extractHsTysRdrTyVars,
+ extractRdrKindSigVars, extractTyDefnKindVars, filterInScope
) where
import {-# SOURCE #-} RnExpr( rnLExpr )
@@ -54,8 +54,9 @@ import BasicTypes ( IPName(..), ipNameName, compareFixity, funTyFixity, negateFi
Fixity(..), FixityDirection(..) )
import Outputable
import FastString
+import Maybes
import Data.List ( nub )
-import Control.Monad ( unless )
+import Control.Monad ( unless, when )
#include "HsVersions.h"
\end{code}
@@ -78,7 +79,7 @@ rnHsSigType doc_str ty = rnLHsType (TypeSigCtx doc_str) ty
rnLHsInstType :: SDoc -> LHsType RdrName -> RnM (LHsType Name, FreeVars)
-- Rename the type in an instance or standalone deriving decl
rnLHsInstType doc_str ty
- = do { (ty', fvs) <- rnLHsType (TypeSigCtx doc_str) ty
+ = do { (ty', fvs) <- rnLHsType (GenericCtx doc_str) ty
; unless good_inst_ty (addErrAt (getLoc ty) (badInstTy ty))
; return (ty', fvs) }
where
@@ -108,13 +109,13 @@ rnLHsType = rnLHsTyKi True
rnLHsKind :: HsDocContext -> LHsKind RdrName -> RnM (LHsKind Name, FreeVars)
rnLHsKind = rnLHsTyKi False
-rnLHsMaybeKind :: HsDocContext -> Maybe (HsBndrSig (LHsKind RdrName))
- -> RnM (Maybe (HsBndrSig (LHsKind Name)), FreeVars)
+rnLHsMaybeKind :: HsDocContext -> Maybe (LHsKind RdrName)
+ -> RnM (Maybe (LHsKind Name), FreeVars)
rnLHsMaybeKind _ Nothing
= return (Nothing, emptyFVs)
-rnLHsMaybeKind doc (Just bsig)
- = rnHsBndrSig False doc bsig $ \ bsig' ->
- return (Just bsig', emptyFVs)
+rnLHsMaybeKind doc (Just kind)
+ = do { (kind', fvs) <- rnLHsKind doc kind
+ ; return (Just kind', fvs) }
rnHsType :: HsDocContext -> HsType RdrName -> RnM (HsType Name, FreeVars)
rnHsType = rnHsTyKi True
@@ -128,33 +129,33 @@ rnHsTyKi isType doc (HsForAllTy Implicit _ lctxt@(L _ ctxt) ty)
-- Implicit quantifiction in source code (no kinds on tyvars)
-- Given the signature C => T we universally quantify
-- over FV(T) \ {in-scope-tyvars}
- name_env <- getLocalRdrEnv
+ rdr_env <- getLocalRdrEnv
loc <- getSrcSpanM
let
- (_kvs, mentioned) = extractHsTysRdrTyVars (ty:ctxt)
+ (forall_kvs, forall_tvs) = filterInScope rdr_env $
+ extractHsTysRdrTyVars (ty:ctxt)
-- In for-all types we don't bring in scope
-- kind variables mentioned in kind signatures
-- (Well, not yet anyway....)
-- f :: Int -> T (a::k) -- Not allowed
- -- Don't quantify over type variables that are in scope;
- -- when GlasgowExts is off, there usually won't be any, except for
- -- class signatures:
- -- class C a where { op :: a -> a }
- forall_tyvars = filter (not . (`elemLocalRdrEnv` name_env)) mentioned
- tyvar_bndrs = userHsTyVarBndrs loc forall_tyvars
+ -- The filterInScope is to ensure that we don't quantify over
+ -- type variables that are in scope; when GlasgowExts is off,
+ -- there usually won't be any, except for class signatures:
+ -- class C a where { op :: a -> a }
+ tyvar_bndrs = userHsTyVarBndrs loc forall_tvs
- rnForAll doc Implicit tyvar_bndrs lctxt ty
+ rnForAll doc Implicit forall_kvs (mkHsQTvs tyvar_bndrs) lctxt ty
rnHsTyKi isType doc ty@(HsForAllTy Explicit forall_tyvars lctxt@(L _ ctxt) tau)
= ASSERT ( isType ) do { -- Explicit quantification.
-- Check that the forall'd tyvars are actually
-- mentioned in the type, and produce a warning if not
- let (_kvs, mentioned) = extractHsTysRdrTyVars (tau:ctxt)
+ let (kvs, mentioned) = extractHsTysRdrTyVars (tau:ctxt)
in_type_doc = ptext (sLit "In the type") <+> quotes (ppr ty)
; warnUnusedForAlls (in_type_doc $$ docOfHsDocContext doc) forall_tyvars mentioned
- ; rnForAll doc Explicit forall_tyvars lctxt tau }
+ ; rnForAll doc Explicit kvs forall_tyvars lctxt tau }
rnHsTyKi isType _ (HsTyVar rdr_name)
= do { name <- rnTyVar isType rdr_name
@@ -310,11 +311,15 @@ rnLHsTypes doc tys = mapFvRn (rnLHsType doc) tys
\begin{code}
-rnForAll :: HsDocContext -> HsExplicitFlag -> [LHsTyVarBndr RdrName]
+rnForAll :: HsDocContext -> HsExplicitFlag
+ -> [RdrName] -- Kind variables
+ -> LHsTyVarBndrs RdrName -- Type variables
-> LHsContext RdrName -> LHsType RdrName
-> RnM (HsType Name, FreeVars)
-rnForAll doc _ [] (L _ []) (L _ ty) = rnHsType doc ty
+rnForAll doc exp kvs forall_tyvars ctxt ty
+ | null kvs, null (hsQTvBndrs forall_tyvars), null (unLoc ctxt)
+ = rnHsType doc (unLoc ty)
-- One reason for this case is that a type like Int#
-- starts off as (HsForAllTy Nothing [] Int), in case
-- there is some quantification. Now that we have quantified
@@ -323,8 +328,8 @@ rnForAll doc _ [] (L _ []) (L _ ty) = rnHsType doc ty
-- get an error, because the body of a genuine for-all is
-- of kind *.
-rnForAll doc exp forall_tyvars ctxt ty
- = bindHsTyVars doc forall_tyvars $ \ new_tyvars ->
+ | otherwise
+ = bindHsTyVars doc Nothing kvs forall_tyvars $ \ new_tyvars ->
do { (new_ctxt, fvs1) <- rnContext doc ctxt
; (new_ty, fvs2) <- rnLHsType doc ty
; return (HsForAllTy exp new_tyvars new_ctxt new_ty, fvs1 `plusFV` fvs2) }
@@ -346,51 +351,70 @@ bindSigTyVarsFV tvs thing_inside
bindLocalNamesFV tvs thing_inside }
---------------
-bindHsTyVars :: HsDocContext -> [LHsTyVarBndr RdrName]
- -> ([LHsTyVarBndr Name] -> RnM (a, FreeVars))
- -> RnM (a, FreeVars)
-bindHsTyVars doc tv_bndrs thing_inside
- = do { checkDupAndShadowedRdrNames rdr_names_w_loc
- ; names <- newLocalBndrsRn rdr_names_w_loc
- ; bindTyVarsRn doc tv_bndrs names thing_inside }
- where
- rdr_names_w_loc = hsLTyVarLocNames tv_bndrs
-
----------------
-bindTyVarsRn :: HsDocContext -> [LHsTyVarBndr RdrName] -> [Name]
- -> ([LHsTyVarBndr Name] -> RnM (a, FreeVars))
- -> RnM (a, FreeVars)
--- Rename the HsTyVarBndrs, giving them the specified names
--- *and* bringing into scope the kind variables bound in
--- any kind signatures
-
-bindTyVarsRn doc tv_bndrs names thing_inside
- = go tv_bndrs names $ \ tv_bndrs' ->
- bindLocalNamesFV names (thing_inside tv_bndrs')
- where
- go [] [] thing_inside = thing_inside []
-
- go (L loc (UserTyVar _) : tvs) (n : ns) thing_inside
- = go tvs ns $ \ tvs' ->
- thing_inside (L loc (UserTyVar n) : tvs')
-
- go (L loc (KindedTyVar _ bsig) : tvs) (n : ns) thing_inside
- = rnHsBndrSig False doc bsig $ \ bsig' ->
- go tvs ns $ \ tvs' ->
- thing_inside (L loc (KindedTyVar n bsig') : tvs')
+bindHsTyVars :: HsDocContext
+ -> Maybe a -- Just _ => an associated type decl
+ -> [RdrName] -- Kind variables from scope
+ -> LHsTyVarBndrs RdrName -- Type variables
+ -> (LHsTyVarBndrs Name -> RnM (b, FreeVars))
+ -> RnM (b, FreeVars)
+-- (a) Bring kind variables into scope
+-- both (i) passed in (kv_bndrs) and (ii) mentioned in the kinds of tv_bndrs
+-- (b) Bring type variables into scope
+bindHsTyVars doc mb_assoc kv_bndrs tv_bndrs thing_inside
+ = do { rdr_env <- getLocalRdrEnv
+ ; let tvs = hsQTvBndrs tv_bndrs
+ kvs_from_tv_bndrs = [ kv | L _ (KindedTyVar _ kind) <- tvs
+ , let (_, kvs) = extractHsTyRdrTyVars kind
+ , kv <- kvs ]
+ all_kvs = filterOut (`elemLocalRdrEnv` rdr_env) $
+ nub (kv_bndrs ++ kvs_from_tv_bndrs)
+ ; poly_kind <- xoptM Opt_PolyKinds
+ ; unless (poly_kind || null all_kvs)
+ (addErr (badKindBndrs doc all_kvs))
+ ; loc <- getSrcSpanM
+ ; kv_names <- mapM (newLocalBndrRn . L loc) all_kvs
+ ; bindLocalNamesFV kv_names $
+ do { let tv_names_w_loc = hsLTyVarLocNames tv_bndrs
+
+ rn_tv_bndr :: LHsTyVarBndr RdrName -> RnM (LHsTyVarBndr Name, FreeVars)
+ rn_tv_bndr (L loc (UserTyVar rdr))
+ = do { nm <- newTyVarNameRn mb_assoc rdr_env loc rdr
+ ; return (L loc (UserTyVar nm), emptyFVs) }
+ rn_tv_bndr (L loc (KindedTyVar rdr kind))
+ = do { sig_ok <- xoptM Opt_KindSignatures
+ ; unless sig_ok (badSigErr False doc kind)
+ ; nm <- newTyVarNameRn mb_assoc rdr_env loc rdr
+ ; (kind', fvs) <- rnLHsKind doc kind
+ ; return (L loc (KindedTyVar nm kind'), fvs) }
+
+ -- Check for duplicate or shadowed tyvar bindrs
+ ; checkDupRdrNames tv_names_w_loc
+ ; when (isNothing mb_assoc) (checkShadowedRdrNames tv_names_w_loc)
+
+ ; (tv_bndrs', fvs1) <- mapFvRn rn_tv_bndr tvs
+ ; (res, fvs2) <- bindLocalNamesFV (map hsLTyVarName tv_bndrs') $
+ do { env <- getLocalRdrEnv
+ ; traceRn (text "bhtv" <+> (ppr tvs $$ ppr all_kvs $$ ppr env))
+ ; thing_inside (HsQTvs { hsq_tvs = tv_bndrs', hsq_kvs = kv_names }) }
+ ; return (res, fvs1 `plusFV` fvs2) } }
- -- Lists of unequal length
- go tvs names _ = pprPanic "bindTyVarsRn" (ppr tvs $$ ppr names)
+newTyVarNameRn :: Maybe a -> LocalRdrEnv -> SrcSpan -> RdrName -> RnM Name
+newTyVarNameRn mb_assoc rdr_env loc rdr
+ | Just _ <- mb_assoc -- Use the same Name as the parent class decl
+ , Just n <- lookupLocalRdrEnv rdr_env rdr
+ = return n
+ | otherwise
+ = newLocalBndrRn (L loc rdr)
--------------------------------
-rnHsBndrSig :: Bool -- True <=> type sig, False <=> kind sig
- -> HsDocContext
- -> HsBndrSig (LHsType RdrName)
- -> (HsBndrSig (LHsType Name) -> RnM (a, FreeVars))
+rnHsBndrSig :: HsDocContext
+ -> HsWithBndrs (LHsType RdrName)
+ -> (HsWithBndrs (LHsType Name) -> RnM (a, FreeVars))
-> RnM (a, FreeVars)
-rnHsBndrSig is_type doc (HsBSig ty@(L loc _) _) thing_inside
- = do { let (kv_bndrs, tv_bndrs) = extractHsTyRdrTyVars ty
- ; checkHsBndrFlags is_type doc ty tv_bndrs
+rnHsBndrSig doc (HsWB { hswb_cts = ty@(L loc _) }) thing_inside
+ = do { sig_ok <- xoptM Opt_ScopedTypeVariables
+ ; unless sig_ok (badSigErr True doc ty)
+ ; let (kv_bndrs, tv_bndrs) = extractHsTyRdrTyVars ty
; name_env <- getLocalRdrEnv
; tv_names <- newLocalBndrsRn [L loc tv | tv <- tv_bndrs
, not (tv `elemLocalRdrEnv` name_env) ]
@@ -398,26 +422,13 @@ rnHsBndrSig is_type doc (HsBSig ty@(L loc _) _) thing_inside
, not (kv `elemLocalRdrEnv` name_env) ]
; bindLocalNamesFV kv_names $
bindLocalNamesFV tv_names $
- do { (ty', fvs1) <- rnLHsTyKi is_type doc ty
- ; (res, fvs2) <- thing_inside (HsBSig ty' (kv_names, tv_names))
+ do { (ty', fvs1) <- rnLHsType doc ty
+ ; (res, fvs2) <- thing_inside (HsWB { hswb_cts = ty', hswb_kvs = kv_names, hswb_tvs = tv_names })
; return (res, fvs1 `plusFV` fvs2) } }
-checkHsBndrFlags :: Bool -> HsDocContext
- -> LHsType RdrName -> [RdrName] -> RnM ()
-checkHsBndrFlags is_type doc ty tv_bndrs
- | is_type -- Type
- = do { sig_ok <- xoptM Opt_ScopedTypeVariables
- ; unless sig_ok (badSigErr True doc ty) }
- | otherwise -- Kind
- = do { sig_ok <- xoptM Opt_KindSignatures
- ; unless sig_ok (badSigErr False doc ty)
- ; poly_kind <- xoptM Opt_PolyKinds
- ; unless (poly_kind || null tv_bndrs)
- (addErr (badKindBndrs doc ty tv_bndrs)) }
-
-badKindBndrs :: HsDocContext -> LHsKind RdrName -> [RdrName] -> SDoc
-badKindBndrs doc _kind kvs
- = vcat [ hang (ptext (sLit "Kind signature mentions kind variable") <> plural kvs
+badKindBndrs :: HsDocContext -> [RdrName] -> SDoc
+badKindBndrs doc kvs
+ = vcat [ hang (ptext (sLit "Unexpected kind variable") <> plural kvs
<+> pprQuotedList kvs)
2 (ptext (sLit "Perhaps you intended to use -XPolyKinds"))
, docOfHsDocContext doc ]
@@ -779,7 +790,7 @@ ppr_opfix (op, fixity) = pp_op <+> brackets (ppr fixity)
%*********************************************************
\begin{code}
-warnUnusedForAlls :: SDoc -> [LHsTyVarBndr RdrName] -> [RdrName] -> TcM ()
+warnUnusedForAlls :: SDoc -> LHsTyVarBndrs RdrName -> [RdrName] -> TcM ()
warnUnusedForAlls in_doc bound mentioned_rdrs
= ifWOptM Opt_WarnUnusedMatches $
mapM_ add_warn bound_but_not_used
@@ -868,8 +879,6 @@ checkTH e what -- Raise an error in a stage-1 compiler
%* *
%************************************************************************
-extractHsTyRdrNames finds the free variables of a HsType
-It's used when making the for-alls explicit.
Note [Kind and type-variable binders]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -902,7 +911,16 @@ See also Note [HsBSig binder lists] in HsTypes
\begin{code}
type FreeKiTyVars = ([RdrName], [RdrName])
+filterInScope :: LocalRdrEnv -> FreeKiTyVars -> FreeKiTyVars
+filterInScope rdr_env (kvs, tvs)
+ = (filterOut in_scope kvs, filterOut in_scope tvs)
+ where
+ in_scope tv = tv `elemLocalRdrEnv` rdr_env
+
extractHsTyRdrTyVars :: LHsType RdrName -> FreeKiTyVars
+-- extractHsTyRdrNames finds the free (kind, type) variables of a HsType
+-- or the free (sort, kind) variables of a HsKind
+-- It's used when making the for-alls explicit.
-- See Note [Kind and type-variable binders]
extractHsTyRdrTyVars ty
= case extract_lty ty ([],[]) of
@@ -914,12 +932,46 @@ extractHsTysRdrTyVars ty
= case extract_ltys ty ([],[]) of
(kvs, tvs) -> (nub kvs, nub tvs)
+extractRdrKindSigVars :: Maybe (LHsKind RdrName) -> [RdrName]
+extractRdrKindSigVars Nothing = []
+extractRdrKindSigVars (Just k) = nub (fst (extract_lkind k ([],[])))
+
+extractTyDefnKindVars :: HsTyDefn RdrName -> [RdrName]
+-- Get the scoped kind variables mentioned free in the constructor decls
+-- Eg data T a = T1 (S (a :: k) | forall (b::k). T2 (S b)
+-- Here k should scope over the whole definition
+extractTyDefnKindVars (TySynonym { td_synRhs = ty})
+ = fst (extractHsTyRdrTyVars ty)
+extractTyDefnKindVars (TyData { td_ctxt = ctxt, td_kindSig = ksig
+ , td_cons = cons, td_derivs = derivs })
+ = fst $ extract_lctxt ctxt $
+ extract_mb extract_lkind ksig $
+ extract_mb extract_ltys derivs $
+ foldr (extract_con . unLoc) ([],[]) cons
+ where
+ extract_con (ConDecl { con_res = ResTyGADT {} }) acc = acc
+ extract_con (ConDecl { con_res = ResTyH98, con_qvars = qvs
+ , con_cxt = ctxt, con_details = details }) acc
+ = extract_hs_tv_bndrs qvs acc $
+ extract_lctxt ctxt $
+ extract_ltys (hsConDeclArgTys details) ([],[])
+
+
extract_lctxt :: LHsContext RdrName -> FreeKiTyVars -> FreeKiTyVars
-extract_lctxt ctxt acc = foldr extract_lty acc (unLoc ctxt)
+extract_lctxt ctxt = extract_ltys (unLoc ctxt)
extract_ltys :: [LHsType RdrName] -> FreeKiTyVars -> FreeKiTyVars
extract_ltys tys acc = foldr extract_lty acc tys
+extract_mb :: (a -> FreeKiTyVars -> FreeKiTyVars) -> Maybe a -> FreeKiTyVars -> FreeKiTyVars
+extract_mb _ Nothing acc = acc
+extract_mb f (Just x) acc = f x acc
+
+extract_lkind :: LHsType RdrName -> FreeKiTyVars -> FreeKiTyVars
+extract_lkind kind (acc_kvs, acc_tvs) = case extract_lty kind ([], acc_kvs) of
+ (_, res_kvs) -> (res_kvs, acc_tvs)
+ -- Kinds shouldn't have sort signatures!
+
extract_lty :: LHsType RdrName -> FreeKiTyVars -> FreeKiTyVars
extract_lty (L _ ty) acc
= case ty of
@@ -943,19 +995,27 @@ extract_lty (L _ ty) acc
HsExplicitTupleTy _ tys -> extract_ltys tys acc
HsTyLit _ -> acc
HsWrapTy _ _ -> panic "extract_lty"
- HsKindSig ty ki -> case extract_lty ty acc of { (kvs1, tvs) ->
- case extract_lty ki ([],kvs1) of { (_, kvs2) ->
- -- Kinds shouldn't have sort signatures!
- (kvs2, tvs) }}
- HsForAllTy _ [] cx ty -> extract_lctxt cx (extract_lty ty acc)
- HsForAllTy _ tvs cx ty -> (acc_kvs ++ body_kvs,
- acc_tvs ++ filterOut (`elem` locals_tvs) body_tvs)
- where
- (body_kvs, body_tvs) = extract_lctxt cx (extract_lty ty ([],[]))
- (acc_kvs, acc_tvs) = acc
- locals_tvs = hsLTyVarNames tvs
- -- Currently we don't have a syntax to explicity bind
- -- kind variables, so these are all type variables
+ HsKindSig ty ki -> extract_lty ty (extract_lkind ki acc)
+ HsForAllTy _ tvs cx ty -> extract_hs_tv_bndrs tvs acc $
+ extract_lctxt cx $
+ extract_lty ty ([],[])
+
+extract_hs_tv_bndrs :: LHsTyVarBndrs RdrName -> FreeKiTyVars
+ -> FreeKiTyVars -> FreeKiTyVars
+extract_hs_tv_bndrs (HsQTvs { hsq_tvs = tvs })
+ acc@(acc_kvs, acc_tvs) -- Note accumulator comes first
+ (body_kvs, body_tvs)
+ | null tvs
+ = (body_kvs ++ acc_kvs, body_tvs ++ acc_tvs)
+ | otherwise
+ = (outer_kvs ++ body_kvs,
+ outer_tvs ++ filterOut (`elem` local_tvs) body_tvs)
+ where
+ local_tvs = map hsLTyVarName tvs
+ -- Currently we don't have a syntax to explicitly bind
+ -- kind variables, so these are all type variables
+
+ (outer_kvs, outer_tvs) = foldr extract_lkind acc [k | L _ (KindedTyVar _ k) <- tvs]
extract_tv :: RdrName -> FreeKiTyVars -> FreeKiTyVars
extract_tv tv acc
diff --git a/compiler/simplCore/SimplUtils.lhs b/compiler/simplCore/SimplUtils.lhs
index 78798b64ad..87aefbab89 100644
--- a/compiler/simplCore/SimplUtils.lhs
+++ b/compiler/simplCore/SimplUtils.lhs
@@ -24,7 +24,8 @@ module SimplUtils (
-- The continuation type
SimplCont(..), DupFlag(..), ArgInfo(..),
isSimplified,
- contIsDupable, contResultType, contIsTrivial, contArgs, dropArgs,
+ contIsDupable, contResultType, contInputType,
+ contIsTrivial, contArgs, dropArgs,
pushSimplifiedArgs, countValArgs, countArgs, addArgTo,
mkBoringStop, mkRhsStop, mkLazyArgStop, contIsRhsOrArg,
interestingCallContext,
@@ -54,7 +55,7 @@ import Var
import Demand
import SimplMonad
import Type hiding( substTy )
-import Coercion hiding( substCo )
+import Coercion hiding( substCo, substTy )
import DataCon ( dataConWorkId )
import VarSet
import BasicTypes
@@ -96,7 +97,8 @@ Key points:
\begin{code}
data SimplCont
- = Stop -- An empty context, or hole, []
+ = Stop -- An empty context, or <hole>
+ OutType -- Type of the <hole>
CallCtxt -- True <=> There is something interesting about
-- the context, and hence the inliner
-- should be a bit keener (see interestingCallContext)
@@ -104,41 +106,43 @@ data SimplCont
-- This is an argument of a function that has RULES
-- Inlining the call might allow the rule to fire
- | CoerceIt -- C `cast` co
+ | CoerceIt -- <hole> `cast` co
OutCoercion -- The coercion simplified
-- Invariant: never an identity coercion
SimplCont
- | ApplyTo -- C arg
+ | ApplyTo -- <hole> arg
DupFlag -- See Note [DupFlag invariants]
InExpr StaticEnv -- The argument and its static env
SimplCont
- | Select -- case C of alts
- DupFlag -- See Note [DupFlag invariants]
- InId InType [InAlt] StaticEnv -- The case binder, alts type, alts, and subst-env
+ | Select -- case <hole> of alts
+ DupFlag -- See Note [DupFlag invariants]
+ InId [InAlt] StaticEnv -- The case binder, alts type, alts, and subst-env
SimplCont
-- The two strict forms have no DupFlag, because we never duplicate them
- | StrictBind -- (\x* \xs. e) C
- InId [InBndr] -- let x* = [] in e
+ | StrictBind -- (\x* \xs. e) <hole>
+ InId [InBndr] -- let x* = <hole> in e
InExpr StaticEnv -- is a special case
SimplCont
- | StrictArg -- f e1 ..en C
+ | StrictArg -- f e1 ..en <hole>
ArgInfo -- Specifies f, e1..en, Whether f has rules, etc
-- plus strictness flags for *further* args
CallCtxt -- Whether *this* argument position is interesting
SimplCont
| TickIt
- (Tickish Id) -- Tick tickish []
+ (Tickish Id) -- Tick tickish <hole>
SimplCont
data ArgInfo
= ArgInfo {
- ai_fun :: Id, -- The function
+ ai_fun :: OutId, -- The function
ai_args :: [OutExpr], -- ...applied to these args (which are in *reverse* order)
+ ai_type :: OutType, -- Type of (f a1 ... an)
+
ai_rules :: [CoreRule], -- Rules for this function
ai_encl :: Bool, -- Flag saying whether this function
@@ -154,18 +158,19 @@ data ArgInfo
}
addArgTo :: ArgInfo -> OutExpr -> ArgInfo
-addArgTo ai arg = ai { ai_args = arg : ai_args ai }
+addArgTo ai arg = ai { ai_args = arg : ai_args ai
+ , ai_type = applyTypeToArg (ai_type ai) arg }
instance Outputable SimplCont where
- ppr (Stop interesting) = ptext (sLit "Stop") <> brackets (ppr interesting)
- ppr (ApplyTo dup arg _ cont) = ((ptext (sLit "ApplyTo") <+> ppr dup <+> pprParendExpr arg)
+ ppr (Stop ty interesting) = ptext (sLit "Stop") <> brackets (ppr interesting) <+> ppr ty
+ ppr (ApplyTo dup arg _ cont) = ((ptext (sLit "ApplyTo") <+> ppr dup <+> pprParendExpr arg)
{- $$ nest 2 (pprSimplEnv se) -}) $$ ppr cont
- ppr (StrictBind b _ _ _ cont) = (ptext (sLit "StrictBind") <+> ppr b) $$ ppr cont
- ppr (StrictArg ai _ cont) = (ptext (sLit "StrictArg") <+> ppr (ai_fun ai)) $$ ppr cont
- ppr (Select dup bndr ty alts se cont) = (ptext (sLit "Select") <+> ppr dup <+> ppr bndr <+> ppr ty) $$
+ ppr (StrictBind b _ _ _ cont) = (ptext (sLit "StrictBind") <+> ppr b) $$ ppr cont
+ ppr (StrictArg ai _ cont) = (ptext (sLit "StrictArg") <+> ppr (ai_fun ai)) $$ ppr cont
+ ppr (Select dup bndr alts se cont) = (ptext (sLit "Select") <+> ppr dup <+> ppr bndr) $$
(nest 2 $ vcat [ppr (seTvSubst se), ppr alts]) $$ ppr cont
- ppr (CoerceIt co cont) = (ptext (sLit "CoerceIt") <+> ppr co) $$ ppr cont
- ppr (TickIt t cont) = (ptext (sLit "TickIt") <+> ppr t) $$ ppr cont
+ ppr (CoerceIt co cont) = (ptext (sLit "CoerceIt") <+> ppr co) $$ ppr cont
+ ppr (TickIt t cont) = (ptext (sLit "TickIt") <+> ppr t) $$ ppr cont
data DupFlag = NoDup -- Unsimplified, might be big
| Simplified -- Simplified
@@ -193,14 +198,14 @@ the following invariants hold
\begin{code}
-------------------
-mkBoringStop :: SimplCont
-mkBoringStop = Stop BoringCtxt
+mkBoringStop :: OutType -> SimplCont
+mkBoringStop ty = Stop ty BoringCtxt
-mkRhsStop :: SimplCont -- See Note [RHS of lets] in CoreUnfold
-mkRhsStop = Stop (ArgCtxt False)
+mkRhsStop :: OutType -> SimplCont -- See Note [RHS of lets] in CoreUnfold
+mkRhsStop ty = Stop ty (ArgCtxt False)
-mkLazyArgStop :: CallCtxt -> SimplCont
-mkLazyArgStop cci = Stop cci
+mkLazyArgStop :: OutType -> CallCtxt -> SimplCont
+mkLazyArgStop ty cci = Stop ty cci
-------------------
contIsRhsOrArg :: SimplCont -> Bool
@@ -211,11 +216,11 @@ contIsRhsOrArg _ = False
-------------------
contIsDupable :: SimplCont -> Bool
-contIsDupable (Stop {}) = True
-contIsDupable (ApplyTo OkToDup _ _ _) = True -- See Note [DupFlag invariants]
-contIsDupable (Select OkToDup _ _ _ _ _) = True -- ...ditto...
-contIsDupable (CoerceIt _ cont) = contIsDupable cont
-contIsDupable _ = False
+contIsDupable (Stop {}) = True
+contIsDupable (ApplyTo OkToDup _ _ _) = True -- See Note [DupFlag invariants]
+contIsDupable (Select OkToDup _ _ _ _) = True -- ...ditto...
+contIsDupable (CoerceIt _ cont) = contIsDupable cont
+contIsDupable _ = False
-------------------
contIsTrivial :: SimplCont -> Bool
@@ -226,28 +231,28 @@ contIsTrivial (CoerceIt _ cont) = contIsTrivial cont
contIsTrivial _ = False
-------------------
-contResultType :: SimplEnv -> OutType -> SimplCont -> OutType
-contResultType env ty cont
- = go cont ty
- where
- subst_ty se ty = SimplEnv.substTy (se `setInScope` env) ty
- subst_co se co = SimplEnv.substCo (se `setInScope` env) co
-
- go (Stop {}) ty = ty
- go (CoerceIt co cont) _ = go cont (pSnd (coercionKind co))
- go (StrictBind _ bs body se cont) _ = go cont (subst_ty se (exprType (mkLams bs body)))
- go (StrictArg ai _ cont) _ = go cont (funResultTy (argInfoResultTy ai))
- go (Select _ _ ty _ se cont) _ = go cont (subst_ty se ty)
- go (ApplyTo _ arg se cont) ty = go cont (apply_to_arg ty arg se)
- go (TickIt _ cont) ty = go cont ty
-
- apply_to_arg ty (Type ty_arg) se = applyTy ty (subst_ty se ty_arg)
- apply_to_arg ty (Coercion co_arg) se = applyCo ty (subst_co se co_arg)
- apply_to_arg ty _ _ = funResultTy ty
-
-argInfoResultTy :: ArgInfo -> OutType
-argInfoResultTy (ArgInfo { ai_fun = fun, ai_args = args })
- = foldr (\arg fn_ty -> applyTypeToArg fn_ty arg) (idType fun) args
+contResultType :: SimplCont -> OutType
+contResultType (Stop ty _) = ty
+contResultType (CoerceIt _ k) = contResultType k
+contResultType (StrictBind _ _ _ _ k) = contResultType k
+contResultType (StrictArg _ _ k) = contResultType k
+contResultType (Select _ _ _ _ k) = contResultType k
+contResultType (ApplyTo _ _ _ k) = contResultType k
+contResultType (TickIt _ k) = contResultType k
+
+contInputType :: SimplCont -> OutType
+contInputType (Stop ty _) = ty
+contInputType (CoerceIt co _) = pFst (coercionKind co)
+contInputType (Select d b _ se _) = perhapsSubstTy d se (idType b)
+contInputType (StrictBind b _ _ se _) = substTy se (idType b)
+contInputType (StrictArg ai _ _) = funArgTy (ai_type ai)
+contInputType (ApplyTo d e se k) = mkFunTy (perhapsSubstTy d se (exprType e)) (contInputType k)
+contInputType (TickIt _ k) = contInputType k
+
+perhapsSubstTy :: DupFlag -> SimplEnv -> InType -> OutType
+perhapsSubstTy dup_flag se ty
+ | isSimplified dup_flag = ty
+ | otherwise = substTy se ty
-------------------
countValArgs :: SimplCont -> Int
@@ -328,7 +333,7 @@ interestingCallContext :: SimplCont -> CallCtxt
interestingCallContext cont
= interesting cont
where
- interesting (Select _ bndr _ _ _ _)
+ interesting (Select _ bndr _ _ _)
| isDeadBinder bndr = CaseCtxt
| otherwise = ArgCtxt False -- If the binder is used, this
-- is like a strict let
@@ -343,7 +348,7 @@ interestingCallContext cont
interesting (StrictArg _ cci _) = cci
interesting (StrictBind {}) = BoringCtxt
- interesting (Stop cci) = cci
+ interesting (Stop _ cci) = cci
interesting (TickIt _ cci) = interesting cci
interesting (CoerceIt _ cont) = interesting cont
-- If this call is the arg of a strict function, the context
@@ -371,16 +376,19 @@ mkArgInfo :: Id
mkArgInfo fun rules n_val_args call_cont
| n_val_args < idArity fun -- Note [Unsaturated functions]
- = ArgInfo { ai_fun = fun, ai_args = [], ai_rules = rules
- , ai_encl = False
+ = ArgInfo { ai_fun = fun, ai_args = [], ai_type = fun_ty
+ , ai_rules = rules, ai_encl = False
, ai_strs = vanilla_stricts
, ai_discs = vanilla_discounts }
| otherwise
- = ArgInfo { ai_fun = fun, ai_args = [], ai_rules = rules
+ = ArgInfo { ai_fun = fun, ai_args = [], ai_type = fun_ty
+ , ai_rules = rules
, ai_encl = interestingArgContext rules call_cont
- , ai_strs = add_type_str (idType fun) arg_stricts
+ , ai_strs = add_type_str fun_ty arg_stricts
, ai_discs = arg_discounts }
where
+ fun_ty = idType fun
+
vanilla_discounts, arg_discounts :: [Int]
vanilla_discounts = repeat 0
arg_discounts = case idUnfolding fun of
@@ -466,7 +474,7 @@ interestingArgContext rules call_cont
go (StrictArg _ cci _) = interesting cci
go (StrictBind {}) = False -- ??
go (CoerceIt _ c) = go c
- go (Stop cci) = interesting cci
+ go (Stop _ cci) = interesting cci
go (TickIt _ c) = go c
interesting (ArgCtxt rules) = rules
diff --git a/compiler/simplCore/Simplify.lhs b/compiler/simplCore/Simplify.lhs
index 8b361b0bc9..56e0bededd 100644
--- a/compiler/simplCore/Simplify.lhs
+++ b/compiler/simplCore/Simplify.lhs
@@ -339,11 +339,14 @@ simplLazyBind env top_lvl is_rec bndr bndr1 rhs rhs_se
-- f = /\a. \x. g a x
-- should eta-reduce
+
; (body_env, tvs') <- simplBinders rhs_env tvs
-- See Note [Floating and type abstraction] in SimplUtils
-- Simplify the RHS
- ; (body_env1, body1) <- simplExprF body_env body mkRhsStop
+ ; let body_out_ty :: OutType
+ body_out_ty = substTy body_env (exprType body)
+ ; (body_env1, body1) <- simplExprF body_env body (mkRhsStop body_out_ty)
-- ANF-ise a constructor or PAP rhs
; (body_env2, body2) <- prepareRhs top_lvl body_env1 bndr1 body1
@@ -879,7 +882,10 @@ might do the same again.
\begin{code}
simplExpr :: SimplEnv -> CoreExpr -> SimplM CoreExpr
-simplExpr env expr = simplExprC env expr mkBoringStop
+simplExpr env expr = simplExprC env expr (mkBoringStop expr_out_ty)
+ where
+ expr_out_ty :: OutType
+ expr_out_ty = substTy env (exprType expr)
simplExprC :: SimplEnv -> CoreExpr -> SimplCont -> SimplM CoreExpr
-- Simplify an expression, given a continuation
@@ -941,17 +947,19 @@ simplExprF1 env expr@(Lam {}) cont
zap b | isTyVar b = b
| otherwise = zapLamIdInfo b
-simplExprF1 env (Case scrut bndr ty alts) cont
+simplExprF1 env (Case scrut bndr alts_ty alts) cont
| sm_case_case (getMode env)
= -- Simplify the scrutinee with a Select continuation
- simplExprF env scrut (Select NoDup bndr ty alts env cont)
+ simplExprF env scrut (Select NoDup bndr alts env cont)
| otherwise
= -- If case-of-case is off, simply simplify the case expression
-- in a vanilla Stop context, and rebuild the result around it
- do { case_expr' <- simplExprC env scrut
- (Select NoDup bndr ty alts env mkBoringStop)
+ do { case_expr' <- simplExprC env scrut
+ (Select NoDup bndr alts env (mkBoringStop alts_out_ty))
; rebuild env case_expr' cont }
+ where
+ alts_out_ty = substTy env alts_ty
simplExprF1 env (Let (Rec pairs) body) cont
= do { env' <- simplRecBndrs env (map fst pairs)
@@ -1105,7 +1113,7 @@ simplTick env tickish expr cont
where (inc,outc) = splitCont c
splitCont (CoerceIt co c) = (CoerceIt co inc, outc)
where (inc,outc) = splitCont c
- splitCont other = (mkBoringStop, other)
+ splitCont other = (mkBoringStop (contInputType other), other)
getDoneId (DoneId id) = id
getDoneId (DoneEx e) = getIdFromTrivialExpr e -- Note [substTickish] in CoreSubst
@@ -1160,7 +1168,7 @@ rebuild env expr cont
Stop {} -> return (env, expr)
CoerceIt co cont -> rebuild env (mkCast expr co) cont
-- NB: mkCast implements the (Coercion co |> g) optimisation
- Select _ bndr ty alts se cont -> rebuildCase (se `setFloats` env) expr bndr ty alts cont
+ Select _ bndr alts se cont -> rebuildCase (se `setFloats` env) expr bndr alts cont
StrictArg info _ cont -> rebuildCall env (info `addArgTo` expr) cont
StrictBind b bs body se cont -> do { env' <- simplNonRecX (se `setFloats` env) b expr
; simplLam env' bs body cont }
@@ -1380,7 +1388,7 @@ simplIdF env var cont
---------------------------------------------------------
-- Dealing with a call site
-completeCall :: SimplEnv -> Id -> SimplCont -> SimplM (SimplEnv, OutExpr)
+completeCall :: SimplEnv -> OutId -> SimplCont -> SimplM (SimplEnv, OutExpr)
completeCall env var cont
= do { ------------- Try inlining ----------------
dflags <- getDynFlags
@@ -1440,14 +1448,14 @@ rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_args, ai_strs = [] }) con
= return (env, castBottomExpr res cont_ty) -- contination to discard, else we do it
where -- again and again!
res = mkApps (Var fun) (reverse rev_args)
- cont_ty = contResultType env (exprType res) cont
+ cont_ty = contResultType cont
rebuildCall env info (ApplyTo dup_flag (Type arg_ty) se cont)
= do { arg_ty' <- if isSimplified dup_flag then return arg_ty
else simplType (se `setInScope` env) arg_ty
; rebuildCall env (info `addArgTo` Type arg_ty') cont }
-rebuildCall env info@(ArgInfo { ai_encl = encl_rules
+rebuildCall env info@(ArgInfo { ai_encl = encl_rules, ai_type = fun_ty
, ai_strs = str:strs, ai_discs = disc:discs })
(ApplyTo dup_flag arg arg_se cont)
| isSimplified dup_flag -- See Note [Avoid redundant simplification]
@@ -1465,7 +1473,7 @@ rebuildCall env info@(ArgInfo { ai_encl = encl_rules
-- have to be very careful about bogus strictness through
-- floating a demanded let.
= do { arg' <- simplExprC (arg_se `setInScope` env) arg
- (mkLazyArgStop cci)
+ (mkLazyArgStop (funArgTy fun_ty) cci)
; rebuildCall env (addArgTo info' arg') cont }
where
info' = info { ai_strs = strs, ai_discs = discs }
@@ -1728,7 +1736,6 @@ rebuildCase, reallyRebuildCase
:: SimplEnv
-> OutExpr -- Scrutinee
-> InId -- Case binder
- -> InType -- Type of alternatives
-> [InAlt] -- Alternatives (inceasing order)
-> SimplCont
-> SimplM (SimplEnv, OutExpr)
@@ -1737,7 +1744,7 @@ rebuildCase, reallyRebuildCase
-- 1. Eliminate the case if there's a known constructor
--------------------------------------------------
-rebuildCase env scrut case_bndr _ alts cont
+rebuildCase env scrut case_bndr alts cont
| Lit lit <- scrut -- No need for same treatment as constructors
-- because literals are inlined more vigorously
, not (litIsLifted lit)
@@ -1766,7 +1773,7 @@ rebuildCase env scrut case_bndr _ alts cont
-- 2. Eliminate the case if scrutinee is evaluated
--------------------------------------------------
-rebuildCase env scrut case_bndr _ [(_, bndrs, rhs)] cont
+rebuildCase env scrut case_bndr [(_, bndrs, rhs)] cont
-- See if we can get rid of the case altogether
-- See Note [Case elimination]
-- mkCase made sure that if all the alternatives are equal,
@@ -1816,7 +1823,7 @@ rebuildCase env scrut case_bndr _ [(_, bndrs, rhs)] cont
-- 3. Try seq rules; see Note [User-defined RULES for seq] in MkId
--------------------------------------------------
-rebuildCase env scrut case_bndr alts_ty alts@[(_, bndrs, rhs)] cont
+rebuildCase env scrut case_bndr alts@[(_, bndrs, rhs)] cont
| all isDeadBinder (case_bndr : bndrs) -- So this is just 'seq'
= do { let rhs' = substExpr (text "rebuild-case") env rhs
out_args = [Type (substTy env (idType case_bndr)),
@@ -1829,24 +1836,25 @@ rebuildCase env scrut case_bndr alts_ty alts@[(_, bndrs, rhs)] cont
Just (n_args, res) -> simplExprF (zapSubstEnv env)
(mkApps res (drop n_args out_args))
cont
- Nothing -> reallyRebuildCase env scrut case_bndr alts_ty alts cont }
+ Nothing -> reallyRebuildCase env scrut case_bndr alts cont }
-rebuildCase env scrut case_bndr alts_ty alts cont
- = reallyRebuildCase env scrut case_bndr alts_ty alts cont
+rebuildCase env scrut case_bndr alts cont
+ = reallyRebuildCase env scrut case_bndr alts cont
--------------------------------------------------
-- 3. Catch-all case
--------------------------------------------------
-reallyRebuildCase env scrut case_bndr alts_ty alts cont
+reallyRebuildCase env scrut case_bndr alts cont
= do { -- Prepare the continuation;
-- The new subst_env is in place
(env', dup_cont, nodup_cont) <- prepareCaseCont env alts cont
-- Simplify the alternatives
- ; (scrut', case_bndr', alts_ty', alts') <- simplAlts env' scrut case_bndr alts_ty alts dup_cont
+ ; (scrut', case_bndr', alts') <- simplAlts env' scrut case_bndr alts dup_cont
; dflags <- getDynFlags
+ ; let alts_ty' = contResultType dup_cont
; case_expr <- mkCase dflags scrut' case_bndr' alts_ty' alts'
-- Notice that rebuild gets the in-scope set from env', not alt_env
@@ -1935,20 +1943,16 @@ robust here. (Otherwise, there's a danger that we'll simply drop the
simplAlts :: SimplEnv
-> OutExpr
-> InId -- Case binder
- -> InType
-> [InAlt] -- Non-empty
-> SimplCont
- -> SimplM (OutExpr, OutId, OutType, [OutAlt]) -- Includes the continuation
+ -> SimplM (OutExpr, OutId, [OutAlt]) -- Includes the continuation
-- Like simplExpr, this just returns the simplified alternatives;
-- it does not return an environment
-- The returned alternatives can be empty, none are possible
-simplAlts env scrut case_bndr alts_ty alts cont'
+simplAlts env scrut case_bndr alts cont'
= do { let env0 = zapFloats env
- ; basic_alts_ty' <- simplType env0 alts_ty
- ; let alts_ty' = contResultType env0 basic_alts_ty' cont'
-
; (env1, case_bndr1) <- simplBinder env0 case_bndr
; fam_envs <- getFamEnvs
@@ -1963,7 +1967,7 @@ simplAlts env scrut case_bndr alts_ty alts cont'
; alts' <- mapM (simplAlt alt_env' mb_var_scrut
imposs_deflt_cons case_bndr' cont') in_alts
; -- pprTrace "simplAlts" (ppr case_bndr $$ ppr alts_ty $$ ppr alts_ty' $$ ppr alts $$ ppr cont') $
- return (scrut', case_bndr', alts_ty', alts') }
+ return (scrut', case_bndr', alts') }
------------------------------------
@@ -2180,11 +2184,9 @@ missingAlt :: SimplEnv -> Id -> [InAlt] -> SimplCont -> SimplM (SimplEnv, OutExp
-- an inner case has no accessible alternatives before
-- it "sees" that the entire branch of an outer case is
-- inaccessible. So we simply put an error case here instead.
-missingAlt env case_bndr alts cont
+missingAlt env case_bndr _ cont
= WARN( True, ptext (sLit "missingAlt") <+> ppr case_bndr )
- return (env, mkImpossibleExpr res_ty)
- where
- res_ty = contResultType env (substTy env (coreAltsType alts)) cont
+ return (env, mkImpossibleExpr (contResultType cont))
\end{code}
@@ -2212,7 +2214,7 @@ prepareCaseCont :: SimplEnv
prepareCaseCont env alts cont
| many_alts alts = mkDupableCont env cont
- | otherwise = return (env, cont, mkBoringStop)
+ | otherwise = return (env, cont, mkBoringStop (contResultType cont))
where
many_alts :: [InAlt] -> Bool -- True iff strictly > 1 non-bottom alternative
many_alts [] = False -- See Note [Bottom alternatives]
@@ -2241,7 +2243,7 @@ mkDupableCont :: SimplEnv -> SimplCont
mkDupableCont env cont
| contIsDupable cont
- = return (env, cont, mkBoringStop)
+ = return (env, cont, mkBoringStop (contResultType cont))
mkDupableCont _ (Stop {}) = panic "mkDupableCont" -- Handled by previous eqn
@@ -2251,10 +2253,10 @@ mkDupableCont env (CoerceIt ty cont)
-- Duplicating ticks for now, not sure if this is good or not
mkDupableCont env cont@(TickIt{})
- = return (env, mkBoringStop, cont)
+ = return (env, mkBoringStop (contInputType cont), cont)
mkDupableCont env cont@(StrictBind {})
- = return (env, mkBoringStop, cont)
+ = return (env, mkBoringStop (contInputType cont), cont)
-- See Note [Duplicating StrictBind]
mkDupableCont env (StrictArg info cci cont)
@@ -2274,16 +2276,16 @@ mkDupableCont env (ApplyTo _ arg se cont)
; let app_cont = ApplyTo OkToDup arg'' (zapSubstEnv env'') dup_cont
; return (env'', app_cont, nodup_cont) }
-mkDupableCont env cont@(Select _ case_bndr _ [(_, bs, _rhs)] _ _)
+mkDupableCont env cont@(Select _ case_bndr [(_, bs, _rhs)] _ _)
-- See Note [Single-alternative case]
-- | not (exprIsDupable rhs && contIsDupable case_cont)
-- | not (isDeadBinder case_bndr)
| all isDeadBinder bs -- InIds
&& not (isUnLiftedType (idType case_bndr))
-- Note [Single-alternative-unlifted]
- = return (env, mkBoringStop, cont)
+ = return (env, mkBoringStop (contInputType cont), cont)
-mkDupableCont env (Select _ case_bndr alts_ty alts se cont)
+mkDupableCont env (Select _ case_bndr alts se cont)
= -- e.g. (case [...hole...] of { pi -> ei })
-- ===>
-- let ji = \xij -> ei
@@ -2299,8 +2301,6 @@ mkDupableCont env (Select _ case_bndr alts_ty alts se cont)
; let alt_env = se `setInScope` env'
- ; basic_alts_ty' <- simplType alt_env alts_ty
- ; let alts_ty' = contResultType alt_env basic_alts_ty' dup_cont
; (alt_env', case_bndr') <- simplBinder alt_env case_bndr
; alts' <- mapM (simplAlt alt_env' Nothing [] case_bndr' dup_cont) alts
-- Safe to say that there are no handled-cons for the DEFAULT case
@@ -2317,7 +2317,8 @@ mkDupableCont env (Select _ case_bndr alts_ty alts se cont)
; (env'', alts'') <- mkDupableAlts env' case_bndr' alts'
; return (env'', -- Note [Duplicated env]
- Select OkToDup case_bndr' alts_ty' alts'' (zapSubstEnv env'') mkBoringStop,
+ Select OkToDup case_bndr' alts'' (zapSubstEnv env'')
+ (mkBoringStop (contInputType nodup_cont)),
nodup_cont) }
diff --git a/compiler/typecheck/Inst.lhs b/compiler/typecheck/Inst.lhs
index d8ba828d9a..0b4364b7ee 100644
--- a/compiler/typecheck/Inst.lhs
+++ b/compiler/typecheck/Inst.lhs
@@ -83,10 +83,11 @@ emitWanteds :: CtOrigin -> TcThetaType -> TcM [EvVar]
emitWanteds origin theta = mapM (emitWanted origin) theta
emitWanted :: CtOrigin -> TcPredType -> TcM EvVar
-emitWanted origin pred = do { loc <- getCtLoc origin
- ; ev <- newWantedEvVar pred
- ; emitFlat (mkNonCanonical (Wanted loc ev))
- ; return ev }
+emitWanted origin pred
+ = do { loc <- getCtLoc origin
+ ; ev <- newWantedEvVar pred
+ ; emitFlat (mkNonCanonical (Wanted { ctev_wloc = loc, ctev_pred = pred, ctev_evar = ev }))
+ ; return ev }
newMethodFromName :: CtOrigin -> Name -> TcRhoType -> TcM (HsExpr TcId)
-- Used when Name is the wired-in name for a wired-in class method,
@@ -530,7 +531,7 @@ tyVarsOfCt (CFunEqCan { cc_tyargs = tys, cc_rhs = xi }) = tyVarsOfTypes (xi:tys)
tyVarsOfCt (CDictCan { cc_tyargs = tys }) = tyVarsOfTypes tys
tyVarsOfCt (CIPCan { cc_ip_ty = ty }) = tyVarsOfType ty
tyVarsOfCt (CIrredEvCan { cc_ty = ty }) = tyVarsOfType ty
-tyVarsOfCt (CNonCanonical { cc_flavor = fl }) = tyVarsOfType (ctFlavPred fl)
+tyVarsOfCt (CNonCanonical { cc_ev = fl }) = tyVarsOfType (ctEvPred fl)
tyVarsOfCDict :: Ct -> TcTyVarSet
tyVarsOfCDict (CDictCan { cc_tyargs = tys }) = tyVarsOfTypes tys
@@ -564,24 +565,22 @@ tyVarsOfBag tvs_of = foldrBag (unionVarSet . tvs_of) emptyVarSet
---------------- Tidying -------------------------
tidyCt :: TidyEnv -> Ct -> Ct
+-- Used only in error reporting
-- Also converts it to non-canonical
tidyCt env ct
- = CNonCanonical { cc_flavor = tidy_flavor env (cc_flavor ct)
+ = CNonCanonical { cc_ev = tidy_flavor env (cc_ev ct)
, cc_depth = cc_depth ct }
- where tidy_flavor :: TidyEnv -> CtFlavor -> CtFlavor
- tidy_flavor env (Given { flav_gloc = gloc, flav_evar = evar })
- = Given { flav_gloc = tidyGivenLoc env gloc
- , flav_evar = tidyEvVar env evar }
- tidy_flavor env (Solved { flav_gloc = gloc
- , flav_evar = evar })
- = Solved { flav_gloc = tidyGivenLoc env gloc
- , flav_evar = tidyEvVar env evar }
- tidy_flavor env (Wanted { flav_wloc = wloc
- , flav_evar = evar })
- = Wanted { flav_wloc = wloc -- Interesting: no tidying needed?
- , flav_evar = tidyEvVar env evar }
- tidy_flavor env (Derived { flav_wloc = wloc, flav_der_pty = pty })
- = Derived { flav_wloc = wloc, flav_der_pty = tidyType env pty }
+ where
+ tidy_flavor :: TidyEnv -> CtEvidence -> CtEvidence
+ -- NB: we do not tidy the ctev_evtm/var field because we don't
+ -- show it in error messages
+ tidy_flavor env ctev@(Given { ctev_gloc = gloc, ctev_pred = pred })
+ = ctev { ctev_gloc = tidyGivenLoc env gloc
+ , ctev_pred = tidyType env pred }
+ tidy_flavor env ctev@(Wanted { ctev_pred = pred })
+ = ctev { ctev_pred = tidyType env pred }
+ tidy_flavor env ctev@(Derived { ctev_pred = pred })
+ = ctev { ctev_pred = tidyType env pred }
tidyEvVar :: TidyEnv -> EvVar -> EvVar
tidyEvVar env var = setVarType var (tidyType env (varType var))
@@ -604,6 +603,10 @@ tidySkolemInfo env (UnifyForAllSkol skol_tvs ty)
tidySkolemInfo _ info = info
---------------- Substitution -------------------------
+-- This is used only in TcSimpify, for substituations that are *also*
+-- reflected in the unification variables. So we don't substitute
+-- in the evidence.
+
substCt :: TvSubst -> Ct -> Ct
-- Conservatively converts it to non-canonical:
-- Postcondition: if the constraint does not get rewritten
@@ -611,9 +614,9 @@ substCt subst ct
| pty <- ctPred ct
, sty <- substTy subst pty
= if sty `eqType` pty then
- ct { cc_flavor = substFlavor subst (cc_flavor ct) }
+ ct { cc_ev = substFlavor subst (cc_ev ct) }
else
- CNonCanonical { cc_flavor = substFlavor subst (cc_flavor ct)
+ CNonCanonical { cc_ev = substFlavor subst (cc_ev ct)
, cc_depth = cc_depth ct }
substWC :: TvSubst -> WantedConstraints -> WantedConstraints
@@ -637,21 +640,16 @@ substImplication subst implic@(Implic { ic_skols = tvs
substEvVar :: TvSubst -> EvVar -> EvVar
substEvVar subst var = setVarType var (substTy subst (varType var))
-substFlavor :: TvSubst -> CtFlavor -> CtFlavor
-substFlavor subst (Given { flav_gloc = gloc, flav_evar = evar })
- = Given { flav_gloc = substGivenLoc subst gloc
- , flav_evar = substEvVar subst evar }
-substFlavor subst (Solved { flav_gloc = gloc, flav_evar = evar })
- = Solved { flav_gloc = substGivenLoc subst gloc
- , flav_evar = substEvVar subst evar }
-
-substFlavor subst (Wanted { flav_wloc = wloc, flav_evar = evar })
- = Wanted { flav_wloc = wloc
- , flav_evar = substEvVar subst evar }
-
-substFlavor subst (Derived { flav_wloc = wloc, flav_der_pty = pty })
- = Derived { flav_wloc = wloc
- , flav_der_pty = substTy subst pty }
+substFlavor :: TvSubst -> CtEvidence -> CtEvidence
+substFlavor subst ctev@(Given { ctev_gloc = gloc, ctev_pred = pred })
+ = ctev { ctev_gloc = substGivenLoc subst gloc
+ , ctev_pred = substTy subst pred }
+
+substFlavor subst ctev@(Wanted { ctev_pred = pred })
+ = ctev { ctev_pred = substTy subst pred }
+
+substFlavor subst ctev@(Derived { ctev_pred = pty })
+ = ctev { ctev_pred = substTy subst pty }
substGivenLoc :: TvSubst -> GivenLoc -> GivenLoc
substGivenLoc subst (CtLoc skol span ctxt)
diff --git a/compiler/typecheck/TcBinds.lhs b/compiler/typecheck/TcBinds.lhs
index 1cc97de8d3..e6e07576d2 100644
--- a/compiler/typecheck/TcBinds.lhs
+++ b/compiler/typecheck/TcBinds.lhs
@@ -379,7 +379,7 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
-- Set up main recover; take advantage of any type sigs
{ traceTc "------------------------------------------------" empty
- ; traceTc "Bindings for" (ppr binder_names)
+ ; traceTc "Bindings for {" (ppr binder_names)
-- -- Instantiate the polytypes of any binders that have signatures
-- -- (as determined by sig_fn), returning a TcSigInfo for each
@@ -390,7 +390,7 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
; let plan = decideGeneralisationPlan dflags type_env
binder_names bind_list sig_fn
; traceTc "Generalisation plan" (ppr plan)
- ; result@(_, poly_ids, _) <- case plan of
+ ; result@(tc_binds, poly_ids, _) <- case plan of
NoGen -> tcPolyNoGen sig_fn prag_fn rec_tc bind_list
InferGen mn cl -> tcPolyInfer mn cl sig_fn prag_fn rec_tc bind_list
CheckGen sig -> tcPolyCheck sig prag_fn rec_tc bind_list
@@ -398,7 +398,10 @@ tcPolyBinds top_lvl sig_fn prag_fn rec_group rec_tc bind_list
-- Check whether strict bindings are ok
-- These must be non-recursive etc, and are not generalised
-- They desugar to a case expression in the end
- ; checkStrictBinds top_lvl rec_group bind_list poly_ids
+ ; checkStrictBinds top_lvl rec_group bind_list tc_binds poly_ids
+ ; traceTc "} End of bindings for" (vcat [ ppr binder_names, ppr rec_group
+ , vcat [ppr id <+> ppr (idType id) | id <- poly_ids]
+ ])
; return result }
where
@@ -1242,21 +1245,32 @@ decideGeneralisationPlan dflags type_env bndr_names lbinds sig_fn
-------------------
checkStrictBinds :: TopLevelFlag -> RecFlag
- -> [LHsBind Name] -> [Id]
+ -> [LHsBind Name]
+ -> LHsBinds TcId -> [Id]
-> TcM ()
-- Check that non-overloaded unlifted bindings are
-- a) non-recursive,
-- b) not top level,
-- c) not a multiple-binding group (more or less implied by (a))
-checkStrictBinds top_lvl rec_group binds poly_ids
+checkStrictBinds top_lvl rec_group orig_binds tc_binds poly_ids
| unlifted || bang_pat
= do { checkTc (isNotTopLevel top_lvl)
- (strictBindErr "Top-level" unlifted binds)
+ (strictBindErr "Top-level" unlifted orig_binds)
; checkTc (isNonRec rec_group)
- (strictBindErr "Recursive" unlifted binds)
- ; checkTc (isSingleton binds)
- (strictBindErr "Multiple" unlifted binds)
+ (strictBindErr "Recursive" unlifted orig_binds)
+
+ ; checkTc (all is_monomorphic (bagToList tc_binds))
+ (polyBindErr orig_binds)
+ -- data Ptr a = Ptr Addr#
+ -- f x = let p@(Ptr y) = ... in ...
+ -- Here the binding for 'p' is polymorphic, but does
+ -- not mix with an unlifted binding for 'y'. You should
+ -- use a bang pattern. Trac #6078.
+
+ ; checkTc (isSingleton orig_binds)
+ (strictBindErr "Multiple" unlifted orig_binds)
+
-- This should be a checkTc, not a warnTc, but as of GHC 6.11
-- the versions of alex and happy available have non-conforming
-- templates, so the GHC build fails if it's an error:
@@ -1267,31 +1281,40 @@ checkStrictBinds top_lvl rec_group binds poly_ids
-- Warn about this, but not about
-- x# = 4# +# 1#
-- (# a, b #) = ...
- (unliftedMustBeBang binds) }
+ (unliftedMustBeBang orig_binds) }
| otherwise
- = return ()
+ = traceTc "csb2" (ppr poly_ids) >>
+ return ()
where
unlifted = any is_unlifted poly_ids
- bang_pat = any (isBangHsBind . unLoc) binds
- lifted_pat = any (isLiftedPatBind . unLoc) binds
+ bang_pat = any (isBangHsBind . unLoc) orig_binds
+ lifted_pat = any (isLiftedPatBind . unLoc) orig_binds
+
is_unlifted id = case tcSplitForAllTys (idType id) of
(_, rho) -> isUnLiftedType rho
+ is_monomorphic (L _ (AbsBinds { abs_tvs = tvs, abs_ev_vars = evs }))
+ = null tvs && null evs
+ is_monomorphic _ = True
+
unliftedMustBeBang :: [LHsBind Name] -> SDoc
unliftedMustBeBang binds
= hang (text "Pattern bindings containing unlifted types should use an outermost bang pattern:")
- 2 (pprBindList binds)
+ 2 (vcat (map ppr binds))
+
+polyBindErr :: [LHsBind Name] -> SDoc
+polyBindErr binds
+ = hang (ptext (sLit "You can't mix polymorphic and unlifted bindings"))
+ 2 (vcat [vcat (map ppr binds),
+ ptext (sLit "Probable fix: use a bang pattern")])
strictBindErr :: String -> Bool -> [LHsBind Name] -> SDoc
strictBindErr flavour unlifted binds
= hang (text flavour <+> msg <+> ptext (sLit "aren't allowed:"))
- 2 (pprBindList binds)
+ 2 (vcat (map ppr binds))
where
msg | unlifted = ptext (sLit "bindings for unlifted types")
| otherwise = ptext (sLit "bang-pattern bindings")
-
-pprBindList :: [LHsBind Name] -> SDoc
-pprBindList binds = vcat (map ppr binds)
\end{code}
diff --git a/compiler/typecheck/TcCanonical.lhs b/compiler/typecheck/TcCanonical.lhs
index d293f0ea3b..2e87c9e2f2 100644
--- a/compiler/typecheck/TcCanonical.lhs
+++ b/compiler/typecheck/TcCanonical.lhs
@@ -173,26 +173,26 @@ EvBinds, so we are again good.
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
canonicalize :: Ct -> TcS StopOrContinue
-canonicalize ct@(CNonCanonical { cc_flavor = fl, cc_depth = d })
+canonicalize ct@(CNonCanonical { cc_ev = fl, cc_depth = d })
= do { traceTcS "canonicalize (non-canonical)" (ppr ct)
; {-# SCC "canEvVar" #-}
canEvVar d fl (classifyPredType (ctPred ct)) }
canonicalize (CDictCan { cc_depth = d
- , cc_flavor = fl
+ , cc_ev = fl
, cc_class = cls
, cc_tyargs = xis })
= {-# SCC "canClass" #-}
canClass d fl cls xis -- Do not add any superclasses
canonicalize (CTyEqCan { cc_depth = d
- , cc_flavor = fl
+ , cc_ev = fl
, cc_tyvar = tv
, cc_rhs = xi })
= {-# SCC "canEqLeafTyVarLeftRec" #-}
canEqLeafTyVarLeftRec d fl tv xi
canonicalize (CFunEqCan { cc_depth = d
- , cc_flavor = fl
+ , cc_ev = fl
, cc_fun = fn
, cc_tyargs = xis1
, cc_rhs = xi2 })
@@ -200,18 +200,18 @@ canonicalize (CFunEqCan { cc_depth = d
canEqLeafFunEqLeftRec d fl (fn,xis1) xi2
canonicalize (CIPCan { cc_depth = d
- , cc_flavor = fl
+ , cc_ev = fl
, cc_ip_nm = nm
, cc_ip_ty = xi })
= canIP d fl nm xi
-canonicalize (CIrredEvCan { cc_flavor = fl
+canonicalize (CIrredEvCan { cc_ev = fl
, cc_depth = d
, cc_ty = xi })
= canIrred d fl xi
canEvVar :: SubGoalDepth
- -> CtFlavor
+ -> CtEvidence
-> PredTree
-> TcS StopOrContinue
-- Called only for non-canonical EvVars
@@ -233,15 +233,16 @@ canEvVar d fl pred_classifier
\begin{code}
canTuple :: SubGoalDepth -- Depth
- -> CtFlavor -> [PredType] -> TcS StopOrContinue
+ -> CtEvidence -> [PredType] -> TcS StopOrContinue
canTuple d fl tys
= do { traceTcS "can_pred" (text "TuplePred!")
; let xcomp = EvTupleMk
xdecomp x = zipWith (\_ i -> EvTupleSel x i) tys [0..]
- ; xCtFlavor fl tys (XEvTerm xcomp xdecomp) what_next }
- where what_next fls = mapM_ add_to_work fls >> return Stop
- add_to_work fl = addToWork $ canEvVar d fl (classifyPredType (ctFlavPred fl))
-
+ ; ctevs <- xCtFlavor fl tys (XEvTerm xcomp xdecomp)
+ ; mapM_ add_to_work ctevs
+ ; return Stop }
+ where
+ add_to_work fl = addToWork $ canEvVar d fl (classifyPredType (ctEvPred fl))
\end{code}
@@ -253,7 +254,7 @@ canTuple d fl tys
\begin{code}
canIP :: SubGoalDepth -- Depth
- -> CtFlavor
+ -> CtEvidence
-> IPName Name -> Type -> TcS StopOrContinue
-- Precondition: EvVar is implicit parameter evidence
canIP d fl nm ty
@@ -264,7 +265,7 @@ canIP d fl nm ty
; mb <- rewriteCtFlavor fl xi co
; case mb of
Just new_fl -> let IPPred _ xi_in = classifyPredType xi
- in continueWith $ CIPCan { cc_flavor = new_fl
+ in continueWith $ CIPCan { cc_ev = new_fl
, cc_ip_nm = nm, cc_ip_ty = xi_in
, cc_depth = d }
Nothing -> return Stop }
@@ -291,7 +292,7 @@ flattened in the first place to facilitate comparing them.)
\begin{code}
canClass, canClassNC
:: SubGoalDepth -- Depth
- -> CtFlavor
+ -> CtEvidence
-> Class -> [Type] -> TcS StopOrContinue
-- Precondition: EvVar is class evidence
@@ -314,14 +315,14 @@ canClass d fl cls tys
; case mb of
Just new_fl ->
- let (ClassPred cls xis_for_dict) = classifyPredType (ctFlavPred new_fl)
+ let (ClassPred cls xis_for_dict) = classifyPredType (ctEvPred new_fl)
in continueWith $
- CDictCan { cc_flavor = new_fl
+ CDictCan { cc_ev = new_fl
, cc_tyargs = xis_for_dict, cc_class = cls, cc_depth = d }
Nothing -> return Stop }
emitSuperclasses :: Ct -> TcS StopOrContinue
-emitSuperclasses ct@(CDictCan { cc_depth = d, cc_flavor = fl
+emitSuperclasses ct@(CDictCan { cc_depth = d, cc_ev = fl
, cc_tyargs = xis_new, cc_class = cls })
-- Add superclasses of this one here, See Note [Adding superclasses].
-- But only if we are not simplifying the LHS of a rule.
@@ -399,20 +400,19 @@ happen.
\begin{code}
newSCWorkFromFlavored :: SubGoalDepth -- Depth
- -> CtFlavor -> Class -> [Xi] -> TcS ()
+ -> CtEvidence -> Class -> [Xi] -> TcS ()
-- Returns superclasses, see Note [Adding superclasses]
newSCWorkFromFlavored d flavor cls xis
| isDerived flavor
= return () -- Deriveds don't yield more superclasses because we will
-- add them transitively in the case of wanteds.
- | isSolved flavor
- = return ()
| isGiven flavor
= do { let sc_theta = immSuperClasses cls xis
xev = XEvTerm { ev_comp = panic "Can't compose for given!"
- , ev_decomp = \x->zipWith (\_ i->EvSuperClass x i) sc_theta [0..] }
- ; xCtFlavor flavor sc_theta xev (emit_sc_flavs d) }
+ , ev_decomp = \x -> zipWith (\_ i -> EvSuperClass x i) sc_theta [0..] }
+ ; ctevs <- xCtFlavor flavor sc_theta xev
+ ; emit_sc_flavs d ctevs }
| isEmptyVarSet (tyVarsOfTypes xis)
= return () -- Wanteds/Derived with no variables yield no deriveds.
@@ -422,15 +422,17 @@ newSCWorkFromFlavored d flavor cls xis
= do { let sc_rec_theta = transSuperClasses cls xis
impr_theta = filter is_improvement_pty sc_rec_theta
xev = panic "Derived's are not supposed to transform evidence!"
- ; xCtFlavor (Derived (flav_wloc flavor) (ctFlavPred flavor)) impr_theta xev $
- emit_sc_flavs d }
+ der_ev = Derived { ctev_wloc = ctev_wloc flavor, ctev_pred = ctev_pred flavor }
+ ; ctevs <- xCtFlavor der_ev impr_theta xev
+ ; emit_sc_flavs d ctevs }
-emit_sc_flavs :: SubGoalDepth -> [CtFlavor] -> TcS ()
+emit_sc_flavs :: SubGoalDepth -> [CtEvidence] -> TcS ()
emit_sc_flavs d fls
= do { traceTcS "newSCWorkFromFlavored" $
text "Emitting superclass work:" <+> ppr sc_cts
; updWorkListTcS $ appendWorkListCt sc_cts }
- where sc_cts = map (\fl -> CNonCanonical { cc_flavor = fl, cc_depth = d }) fls
+ where
+ sc_cts = map (\fl -> CNonCanonical { cc_ev = fl, cc_depth = d }) fls
is_improvement_pty :: PredType -> Bool
-- Either it's an equality, or has some functional dependency
@@ -454,7 +456,7 @@ is_improvement_pty ty = go (classifyPredType ty)
\begin{code}
canIrred :: SubGoalDepth -- Depth
- -> CtFlavor -> TcType -> TcS StopOrContinue
+ -> CtEvidence -> TcType -> TcS StopOrContinue
-- Precondition: ty not a tuple and no other evidence form
canIrred d fl ty
= do { traceTcS "can_pred" (text "IrredPred = " <+> ppr ty)
@@ -468,9 +470,9 @@ canIrred d fl ty
Just new_fl
| no_flattening
-> continueWith $
- CIrredEvCan { cc_flavor = new_fl, cc_ty = xi, cc_depth = d }
+ CIrredEvCan { cc_ev = new_fl, cc_ty = xi, cc_depth = d }
| otherwise
- -> canEvVar d new_fl (classifyPredType (ctFlavPred new_fl))
+ -> canEvVar d new_fl (classifyPredType (ctEvPred new_fl))
Nothing -> return Stop }
\end{code}
@@ -529,7 +531,7 @@ data FlattenMode = FMSubstOnly
-- Flatten a bunch of types all at once.
flattenMany :: SubGoalDepth -- Depth
-> FlattenMode
- -> CtFlavor -> [Type] -> TcS ([Xi], [TcCoercion])
+ -> CtEvidence -> [Type] -> TcS ([Xi], [TcCoercion])
-- Coercions :: Xi ~ Type
-- Returns True iff (no flattening happened)
-- NB: The EvVar inside the flavor is unused, we merely want Given/Solved/Derived/Wanted info
@@ -546,7 +548,7 @@ flattenMany d f ctxt tys
-- constraints. See Note [Flattening] for more detail.
flatten :: SubGoalDepth -- Depth
-> FlattenMode
- -> CtFlavor -> TcType -> TcS (Xi, TcCoercion)
+ -> CtEvidence -> TcType -> TcS (Xi, TcCoercion)
-- Postcondition: Coercion :: Xi ~ TcType
flatten d f ctxt ty
| Just ty' <- tcView ty
@@ -595,7 +597,8 @@ flatten d f fl (TyConApp tc tys)
do { flat_cache <- getFlatCache
; case lookupTM fam_ty flat_cache of
Just ct
- | cc_flavor ct `canRewrite` fl
+ | let ctev = cc_ev ct
+ , ctev `canRewrite` fl
-> -- You may think that we can just return (cc_rhs ct) but not so.
-- return (mkTcCoVarCo (ctId ct), cc_rhs ct, [])
-- The cached constraint resides in the cache so we have to flatten
@@ -606,42 +609,42 @@ flatten d f fl (TyConApp tc tys)
-- For now I say we don't keep it fully rewritten.
do { traceTcS "flatten/flat-cache hit" $ ppr ct
; let rhs_xi = cc_rhs ct
- ; (flat_rhs_xi,co) <- flatten (cc_depth ct) f (cc_flavor ct) rhs_xi
- ; let final_co = mkTcCoVarCo (ctId ct) `mkTcTransCo` (mkTcSymCo co)
+ ; (flat_rhs_xi,co) <- flatten (cc_depth ct) f ctev rhs_xi
+ ; let final_co = evTermCoercion (ctEvTerm ctev)
+ `mkTcTransCo` mkTcSymCo co
; return (final_co, flat_rhs_xi,[]) }
- _ | isGivenOrSolved fl -- Given or Solved: make new flatten skolem
+ _ | isGiven fl -- Given: make new flatten skolem
-> do { traceTcS "flatten/flat-cache miss" $ empty
; rhs_xi_var <- newFlattenSkolemTy fam_ty
- ; mg <- newGivenEvVar (mkTcEqPred fam_ty rhs_xi_var)
- (EvCoercion (mkTcReflCo fam_ty))
- ; case mg of
- Fresh eqv ->
- do { let new_fl = Given (flav_gloc fl) eqv
- ct = CFunEqCan { cc_flavor = new_fl
- , cc_fun = tc
- , cc_tyargs = xi_args
- , cc_rhs = rhs_xi_var
- , cc_depth = d }
- -- Update the flat cache
- ; updFlatCache ct
- ; return (mkTcCoVarCo eqv, rhs_xi_var, [ct]) }
- Cached {} -> panic "flatten TyConApp, var must be fresh!" }
+ ; let co = mkTcReflCo fam_ty
+ new_fl = Given { ctev_gloc = ctev_gloc fl
+ , ctev_pred = mkTcEqPred fam_ty rhs_xi_var
+ , ctev_evtm = EvCoercion co }
+ ct = CFunEqCan { cc_ev = new_fl
+ , cc_fun = tc
+ , cc_tyargs = xi_args
+ , cc_rhs = rhs_xi_var
+ , cc_depth = d }
+ -- Update the flat cache
+ ; updFlatCache ct
+ ; return (co, rhs_xi_var, [ct]) }
| otherwise -- Wanted or Derived: make new unification variable
-> do { traceTcS "flatten/flat-cache miss" $ empty
; rhs_xi_var <- newFlexiTcSTy (typeKind fam_ty)
- ; mw <- newWantedEvVar (mkTcEqPred fam_ty rhs_xi_var)
+ ; let pred = mkTcEqPred fam_ty rhs_xi_var
+ wloc = ctev_wloc fl
+ ; mw <- newWantedEvVar wloc pred
; case mw of
- Fresh eqv ->
- do { let new_fl = Wanted (flav_wloc fl) eqv
- ct = CFunEqCan { cc_flavor = new_fl
+ Fresh ctev ->
+ do { let ct = CFunEqCan { cc_ev = ctev
, cc_fun = tc
, cc_tyargs = xi_args
, cc_rhs = rhs_xi_var
, cc_depth = d }
-- Update the flat cache: just an optimisation!
; updFlatCache ct
- ; return (mkTcCoVarCo eqv, rhs_xi_var, [ct]) }
+ ; return (evTermCoercion (ctEvTerm ctev), rhs_xi_var, [ct]) }
Cached {} -> panic "flatten TyConApp, var must be fresh!" }
}
-- Emit the flat constraints
@@ -691,7 +694,7 @@ flatten d _f ctxt ty@(ForAllTy {})
\begin{code}
flattenTyVar :: SubGoalDepth
-> FlattenMode
- -> CtFlavor -> TcTyVar -> TcS (Xi, TcCoercion)
+ -> CtEvidence -> TcTyVar -> TcS (Xi, TcCoercion)
-- "Flattening" a type variable means to apply the substitution to it
flattenTyVar d f ctxt tv
= do { ieqs <- getInertEqs
@@ -709,13 +712,15 @@ flattenTyVar d f ctxt tv
Just (co,ty) ->
do { (ty_final,co') <- flatten d f ctxt ty
; return (ty_final, co' `mkTcTransCo` mkTcSymCo co) } }
- where tv_eq_subst subst tv
- | Just ct <- lookupVarEnv subst tv
- , cc_flavor ct `canRewrite` ctxt
- = Just (mkTcCoVarCo (ctId ct),cc_rhs ct)
- -- NB: even if ct is Derived we are not going to
- -- touch the actual coercion so we are fine.
- | otherwise = Nothing
+ where
+ tv_eq_subst subst tv
+ | Just ct <- lookupVarEnv subst tv
+ , let ctev = cc_ev ct
+ , ctev `canRewrite` ctxt
+ = Just (evTermCoercion (ctEvTerm ctev), cc_rhs ct)
+ -- NB: even if ct is Derived we are not going to
+ -- touch the actual coercion so we are fine.
+ | otherwise = Nothing
\end{code}
Note [Non-idempotent inert substitution]
@@ -765,13 +770,13 @@ addToWork tcs_action = tcs_action >>= stop_or_emit
\begin{code}
canEqEvVarsCreated :: SubGoalDepth
- -> [CtFlavor] -> TcS StopOrContinue
+ -> [CtEvidence] -> TcS StopOrContinue
canEqEvVarsCreated _d [] = return Stop
canEqEvVarsCreated d (quad:quads)
= mapM_ (addToWork . do_quad) quads >> do_quad quad
-- Add all but one to the work list
-- and return the first (if any) for futher processing
- where do_quad fl = let EqPred ty1 ty2 = classifyPredType $ ctFlavPred fl
+ where do_quad fl = let EqPred ty1 ty2 = classifyPredType $ ctEvPred fl
in canEqNC d fl ty1 ty2
-- Note the "NC": these are fresh equalities so we must be
-- careful to add their kind constraints
@@ -779,7 +784,7 @@ canEqEvVarsCreated d (quad:quads)
-------------------------
canEqNC, canEq
:: SubGoalDepth
- -> CtFlavor
+ -> CtEvidence
-> Type -> Type -> TcS StopOrContinue
canEqNC d fl ty1 ty2
@@ -790,7 +795,7 @@ canEq _d fl ty1 ty2
| eqType ty1 ty2 -- Dealing with equality here avoids
-- later spurious occurs checks for a~a
= if isWanted fl then
- setEvBind (flav_evar fl) (EvCoercion (mkTcReflCo ty1)) >> return Stop
+ setEvBind (ctev_evar fl) (EvCoercion (mkTcReflCo ty1)) >> return Stop
else
return Stop
@@ -823,11 +828,11 @@ canEq d fl ty1 ty2
-- Fail straight away for better error messages
then canEqFailure d fl
else
- let xcomp xs = EvCoercion (mkTcTyConAppCo tc1 (map mkTcCoVarCo xs))
- xdecomp x = zipWith (\_ i -> EvCoercion $ mkTcNthCo i (mkTcCoVarCo x)) tys1 [0..]
- xev = XEvTerm xcomp xdecomp
- in xCtFlavor fl (zipWith mkTcEqPred tys1 tys2) xev (canEqEvVarsCreated d)
-
+ do { let xcomp xs = EvCoercion (mkTcTyConAppCo tc1 (map evTermCoercion xs))
+ xdecomp x = zipWith (\_ i -> EvCoercion $ mkTcNthCo i (evTermCoercion x)) tys1 [0..]
+ xev = XEvTerm xcomp xdecomp
+ ; ctevs <- xCtFlavor fl (zipWith mkTcEqPred tys1 tys2) xev
+ ; canEqEvVarsCreated d ctevs }
-- See Note [Equality between type applications]
-- Note [Care with type applications] in TcUnify
@@ -839,7 +844,7 @@ canEq d fl ty1 ty2 -- e.g. F a b ~ Maybe c
canEq d fl s1@(ForAllTy {}) s2@(ForAllTy {})
| tcIsForAllTy s1, tcIsForAllTy s2
- , Wanted loc orig_ev <- fl
+ , Wanted { ctev_wloc = loc, ctev_evar = orig_ev } <- fl
= do { let (tvs1,body1) = tcSplitForAllTys s1
(tvs2,body2) = tcSplitForAllTys s2
; if not (equalLength tvs1 tvs2) then
@@ -857,12 +862,12 @@ canEq d fl _ _ = canEqFailure d fl
------------------------
-- Type application
canEqAppTy :: SubGoalDepth
- -> CtFlavor
+ -> CtEvidence
-> Type -> Type -> Type -> Type
-> TcS StopOrContinue
canEqAppTy d fl s1 t1 s2 t2
= ASSERT( not (isKind t1) && not (isKind t2) )
- if isGivenOrSolved fl then
+ if isGiven fl then
do { traceTcS "canEq (app case)" $
text "Ommitting decomposition of given equality between: "
<+> ppr (AppTy s1 t1) <+> text "and" <+> ppr (AppTy s2 t2)
@@ -870,14 +875,14 @@ canEqAppTy d fl s1 t1 s2 t2
-- because we no longer have 'left' and 'right'
; return Stop }
else
- let xevcomp [x,y] = EvCoercion (mkTcAppCo (mkTcCoVarCo x) (mkTcCoVarCo y))
- xevcomp _ = error "canEqAppTy: can't happen" -- Can't happen
- xev = XEvTerm { ev_comp = xevcomp
- , ev_decomp = error "canEqAppTy: can't happen" }
- in xCtFlavor fl [mkTcEqPred s1 s2, mkTcEqPred t1 t2] xev $
- canEqEvVarsCreated d
-
-canEqFailure :: SubGoalDepth -> CtFlavor -> TcS StopOrContinue
+ do { let xevcomp [x,y] = EvCoercion (mkTcAppCo (evTermCoercion x) (evTermCoercion y))
+ xevcomp _ = error "canEqAppTy: can't happen" -- Can't happen
+ xev = XEvTerm { ev_comp = xevcomp
+ , ev_decomp = error "canEqAppTy: can't happen" }
+ ; ctevs <- xCtFlavor fl [mkTcEqPred s1 s2, mkTcEqPred t1 t2] xev
+ ; canEqEvVarsCreated d ctevs }
+
+canEqFailure :: SubGoalDepth -> CtEvidence -> TcS StopOrContinue
canEqFailure d fl = emitFrozenError fl d >> return Stop
------------------------
@@ -885,12 +890,12 @@ emitKindConstraint :: Ct -> TcS StopOrContinue
emitKindConstraint ct
= case ct of
CTyEqCan { cc_depth = d
- , cc_flavor = fl, cc_tyvar = tv
+ , cc_ev = fl, cc_tyvar = tv
, cc_rhs = ty }
-> emit_kind_constraint d fl (mkTyVarTy tv) ty
CFunEqCan { cc_depth = d
- , cc_flavor = fl
+ , cc_ev = fl
, cc_fun = fn, cc_tyargs = xis1
, cc_rhs = xi2 }
-> emit_kind_constraint d fl (mkTyConApp fn xis1) xi2
@@ -904,41 +909,43 @@ emitKindConstraint ct
| otherwise
= ASSERT( isKind k1 && isKind k2 )
do { kev <-
- do { mw <- newWantedEvVar (mkEqPred k1 k2)
+ do { mw <- newWantedEvVar kind_co_wloc (mkEqPred k1 k2)
; case mw of
- Cached x -> return x
- Fresh x -> addToWork (canEq d (kind_co_fl x) k1 k2) >> return x }
- ; let xcomp [x] = mkEvKindCast x (mkTcCoVarCo kev)
+ Cached ev_tm -> return ev_tm
+ Fresh ctev -> do { addToWork (canEq d ctev k1 k2)
+ ; return (ctEvTerm ctev) } }
+
+ ; let xcomp [x] = mkEvKindCast x (evTermCoercion kev)
xcomp _ = panic "emit_kind_constraint:can't happen"
- xdecomp x = [mkEvKindCast x (mkTcCoVarCo kev)]
+ xdecomp x = [mkEvKindCast x (evTermCoercion kev)]
xev = XEvTerm xcomp xdecomp
- in xCtFlavor_cache False fl [mkTcEqPred ty1 ty2] xev what_next }
+
+ ; ctevs <- xCtFlavor_cache False fl [mkTcEqPred ty1 ty2] xev
-- Important: Do not cache original as Solved since we are supposed to
-- solve /exactly/ the same constraint later! Example:
-- (alpha :: kappa0)
-- (T :: *)
-- Equality is: (alpha ~ T), so we will emitConstraint (kappa0 ~ *) but
-- we don't want to say that (alpha ~ T) is now Solved!
- where
- what_next [new_fl] = continueWith (ct { cc_flavor = new_fl })
- what_next _ = return Stop
+ ; case ctevs of
+ [] -> return Stop
+ [new_ctev] -> continueWith (ct { cc_ev = new_ctev })
+ _ -> panic "emitKindConstraint" }
+ where
k1 = typeKind ty1
k2 = typeKind ty2
ctxt = mkKindErrorCtxtTcS ty1 k1 ty2 k2
+
-- Always create a Wanted kind equality even if
-- you are decomposing a given constraint.
-- NB: DV finds this reasonable for now. Maybe we have to revisit.
- kind_co_fl x
- | isGivenOrSolved fl
- = let (CtLoc _sk_info src_span err_ctxt) = flav_gloc fl
- orig = TypeEqOrigin (UnifyOrigin ty1 ty2)
- ctloc = pushErrCtxtSameOrigin ctxt $
- CtLoc orig src_span err_ctxt
- in Wanted ctloc x
- | otherwise
- = Wanted (pushErrCtxtSameOrigin ctxt (flav_wloc fl)) x
-
+ kind_co_wloc = pushErrCtxtSameOrigin ctxt wanted_loc
+ wanted_loc = case fl of
+ Wanted { ctev_wloc = wloc } -> wloc
+ Derived { ctev_wloc = wloc } -> wloc
+ Given { ctev_gloc = gloc } -> setCtLocOrigin gloc orig
+ orig = TypeEqOrigin (UnifyOrigin ty1 ty2)
\end{code}
Note [Combining insoluble constraints]
@@ -1106,7 +1113,7 @@ classify ty | Just ty' <- tcView ty
= OtherCls ty
-- See note [Canonical ordering for equality constraints].
-reOrient :: CtFlavor -> TypeClassifier -> TypeClassifier -> Bool
+reOrient :: CtEvidence -> TypeClassifier -> TypeClassifier -> Bool
-- (t1 `reOrient` t2) responds True
-- iff we should flip to (t2~t1)
-- We try to say False if possible, to minimise evidence generation
@@ -1143,7 +1150,7 @@ reOrient _fl (FskCls {}) (OtherCls {}) = False
------------------
canEqLeaf :: SubGoalDepth -- Depth
- -> CtFlavor
+ -> CtEvidence
-> Type -> Type
-> TcS StopOrContinue
-- Canonicalizing "leaf" equality constraints which cannot be
@@ -1156,13 +1163,16 @@ canEqLeaf :: SubGoalDepth -- Depth
canEqLeaf d fl s1 s2
| cls1 `re_orient` cls2
= do { traceTcS "canEqLeaf (reorienting)" $ ppr fl <+> dcolon <+> pprEq s1 s2
- ; let xcomp [x] = EvCoercion (mkTcSymCo (mkTcCoVarCo x))
+ ; let xcomp [x] = EvCoercion (mkTcSymCo (evTermCoercion x))
xcomp _ = panic "canEqLeaf: can't happen"
- xdecomp x = [EvCoercion (mkTcSymCo (mkTcCoVarCo x))]
+ xdecomp x = [EvCoercion (mkTcSymCo (evTermCoercion x))]
xev = XEvTerm xcomp xdecomp
- what_next [fl] = canEqLeafOriented d fl s2 s1
- what_next _ = return Stop
- ; xCtFlavor fl [mkTcEqPred s2 s1] xev what_next }
+ ; ctevs <- xCtFlavor fl [mkTcEqPred s2 s1] xev
+ ; case ctevs of
+ [] -> return Stop
+ [ctev] -> canEqLeafOriented d ctev s2 s1
+ _ -> panic "canEqLeaf" }
+
| otherwise
= do { traceTcS "canEqLeaf" $ ppr (mkTcEqPred s1 s2)
; canEqLeafOriented d fl s1 s2 }
@@ -1172,7 +1182,7 @@ canEqLeaf d fl s1 s2
cls2 = classify s2
canEqLeafOriented :: SubGoalDepth -- Depth
- -> CtFlavor
+ -> CtEvidence
-> TcType -> TcType -> TcS StopOrContinue
-- By now s1 will either be a variable or a type family application
canEqLeafOriented d fl s1 s2
@@ -1184,10 +1194,10 @@ canEqLeafOriented d fl s1 s2
= canEqLeafTyVarLeftRec d fl tv s2
| otherwise
= pprPanic "canEqLeafOriented" $
- text "Non-variable or non-family equality LHS" <+> ppr (ctFlavPred fl)
+ text "Non-variable or non-family equality LHS" <+> ppr (ctEvPred fl)
canEqLeafFunEqLeftRec :: SubGoalDepth
- -> CtFlavor
+ -> CtEvidence
-> (TyCon,[TcType]) -> TcType -> TcS StopOrContinue
canEqLeafFunEqLeftRec d fl (fn,tys1) ty2 -- fl :: F tys1 ~ ty2
= do { traceTcS "canEqLeafFunEqLeftRec" $ pprEq (mkTyConApp fn tys1) ty2
@@ -1210,7 +1220,7 @@ canEqLeafFunEqLeftRec d fl (fn,tys1) ty2 -- fl :: F tys1 ~ ty2
canEqLeafFunEqLeft :: SubGoalDepth -- Depth
- -> CtFlavor
+ -> CtEvidence
-> (TyCon,[Xi])
-> TcType -> TcS StopOrContinue
-- Precondition: No more flattening is needed for the LHS
@@ -1232,12 +1242,12 @@ canEqLeafFunEqLeft d fl (fn,xis1) s2
; case mb of
Nothing -> return Stop
Just new_fl -> continueWith $
- CFunEqCan { cc_flavor = new_fl, cc_depth = d
+ CFunEqCan { cc_ev = new_fl, cc_depth = d
, cc_fun = fn, cc_tyargs = xis1, cc_rhs = xi2 } }
canEqLeafTyVarLeftRec :: SubGoalDepth
- -> CtFlavor
+ -> CtEvidence
-> TcTyVar -> TcType -> TcS StopOrContinue
canEqLeafTyVarLeftRec d fl tv s2 -- fl :: tv ~ s2
= do { traceTcS "canEqLeafTyVarLeftRec" $ pprEq (mkTyVarTy tv) s2
@@ -1262,7 +1272,7 @@ canEqLeafTyVarLeftRec d fl tv s2 -- fl :: tv ~ s2
Nothing -> canEq d new_fl xi1 s2 }
canEqLeafTyVarLeft :: SubGoalDepth -- Depth
- -> CtFlavor
+ -> CtEvidence
-> TcTyVar -> TcType -> TcS StopOrContinue
-- Precondition LHS is fully rewritten from inerts (but not RHS)
canEqLeafTyVarLeft d fl tv s2 -- eqv : tv ~ s2
@@ -1276,7 +1286,7 @@ canEqLeafTyVarLeft d fl tv s2 -- eqv : tv ~ s2
-- Reflexivity exposed through flattening
; if tv_ty `eqType` xi2 then
- when (isWanted fl) (setEvBind (flav_evar fl) (EvCoercion co2)) >>
+ when (isWanted fl) (setEvBind (ctev_evar fl) (EvCoercion co2)) >>
return Stop
else do
-- Not reflexivity but maybe an occurs error
@@ -1291,7 +1301,7 @@ canEqLeafTyVarLeft d fl tv s2 -- eqv : tv ~ s2
; case mb of
Just new_fl -> if not_occ_err then
continueWith $
- CTyEqCan { cc_flavor = new_fl, cc_depth = d
+ CTyEqCan { cc_ev = new_fl, cc_depth = d
, cc_tyvar = tv, cc_rhs = xi2' }
else
canEqFailure d new_fl
@@ -1307,7 +1317,7 @@ canEqLeafTyVarLeft d fl tv s2 -- eqv : tv ~ s2
-- variable, then the same type is returned.
--
-- Precondition: the two types are not equal (looking though synonyms)
-canOccursCheck :: CtFlavor -> TcTyVar -> Xi -> TcS (Maybe Xi)
+canOccursCheck :: CtEvidence -> TcTyVar -> Xi -> TcS (Maybe Xi)
canOccursCheck _gw tv xi = return (expandAway tv xi)
\end{code}
diff --git a/compiler/typecheck/TcErrors.lhs b/compiler/typecheck/TcErrors.lhs
index 020d42c1ba..483de071d4 100644
--- a/compiler/typecheck/TcErrors.lhs
+++ b/compiler/typecheck/TcErrors.lhs
@@ -158,17 +158,15 @@ reportTidyWanteds ctxt insols flats implics
deferToRuntime :: EvBindsVar -> ReportErrCtxt -> (ReportErrCtxt -> Ct -> TcM ErrMsg)
-> Ct -> TcM ()
deferToRuntime ev_binds_var ctxt mk_err_msg ct
- | fl <- cc_flavor ct
- , Wanted loc _ <- fl
+ | Wanted { ctev_wloc = loc, ctev_pred = pred, ctev_evar = ev_id } <- cc_ev ct
= do { err <- setCtLoc loc $
mk_err_msg ctxt ct
- ; let ev_id = ctId ct -- Prec satisfied: Wanted
- err_msg = pprLocErrMsg err
+ ; let err_msg = pprLocErrMsg err
err_fs = mkFastString $ showSDoc $
err_msg $$ text "(deferred type error)"
-- Create the binding
- ; addTcEvBind ev_binds_var ev_id (EvDelayedError (idType ev_id) err_fs)
+ ; addTcEvBind ev_binds_var ev_id (EvDelayedError pred err_fs)
-- And emit a warning
; reportWarning (makeIntoWarning err) }
@@ -231,7 +229,7 @@ type Reporter = [Ct] -> TcM ()
mkReporter :: (Ct -> TcM ErrMsg) -> [Ct] -> TcM ()
-- Reports errors one at a time
-mkReporter mk_err = mapM_ (\ct -> do { err <- setCtFlavorLoc (cc_flavor ct) $
+mkReporter mk_err = mapM_ (\ct -> do { err <- setCtFlavorLoc (cc_ev ct) $
mk_err ct;
; reportError err })
@@ -316,15 +314,15 @@ groupErrs mk_err (ct1 : rest)
; reportError err
; groupErrs mk_err others }
where
- flavor = cc_flavor ct1
+ flavor = cc_ev ct1
cts = ct1 : friends
(friends, others) = partition is_friend rest
- is_friend friend = cc_flavor friend `same_group` flavor
+ is_friend friend = cc_ev friend `same_group` flavor
- same_group :: CtFlavor -> CtFlavor -> Bool
- same_group (Given l1 _) (Given l2 _) = same_loc l1 l2
- same_group (Derived l1 _) (Derived l2 _) = same_loc l1 l2
- same_group (Wanted l1 _) (Wanted l2 _) = same_loc l1 l2
+ same_group :: CtEvidence -> CtEvidence -> Bool
+ same_group (Given {ctev_gloc = l1}) (Given {ctev_gloc = l2}) = same_loc l1 l2
+ same_group (Wanted {ctev_wloc = l1}) (Wanted {ctev_wloc = l2}) = same_loc l1 l2
+ same_group (Derived {ctev_wloc = l1}) (Derived {ctev_wloc = l2}) = same_loc l1 l2
same_group _ _ = False
same_loc :: CtLoc o -> CtLoc o -> Bool
@@ -425,7 +423,7 @@ mkEqErr _ [] = panic "mkEqErr"
mkEqErr1 :: ReportErrCtxt -> Ct -> TcM ErrMsg
-- Wanted constraints only!
mkEqErr1 ctxt ct
- = if isGivenOrSolved flav then
+ = if isGiven flav then
let ctx2 = ctxt { cec_extra = cec_extra ctxt $$ inaccessible_msg flav }
in mkEqErr_help ctx2 ct False ty1 ty2
else
@@ -434,10 +432,11 @@ mkEqErr1 ctxt ct
; mk_err ctxt1 orig' }
where
- flav = cc_flavor ct
+ flav = cc_ev ct
- inaccessible_msg (Given loc _) = hang (ptext (sLit "Inaccessible code in"))
- 2 (ppr (ctLocOrigin loc))
+ inaccessible_msg (Given { ctev_gloc = loc })
+ = hang (ptext (sLit "Inaccessible code in"))
+ 2 (ppr (ctLocOrigin loc))
-- If a Solved then we should not report inaccessible code
inaccessible_msg _ = empty
@@ -571,7 +570,7 @@ misMatchOrCND :: ReportErrCtxt -> Ct -> Bool -> TcType -> TcType -> SDoc
misMatchOrCND ctxt ct oriented ty1 ty2
| null givens ||
(isRigid ty1 && isRigid ty2) ||
- isGivenOrSolved (cc_flavor ct)
+ isGiven (cc_ev ct)
-- If the equality is unconditionally insoluble
-- or there is no context, don't report the context
= misMatchMsg oriented ty1 ty2
@@ -1066,7 +1065,7 @@ solverDepthErrorTcS depth stack
| null stack -- Shouldn't happen unless you say -fcontext-stack=0
= failWith msg
| otherwise
- = setCtFlavorLoc (cc_flavor top_item) $
+ = setCtFlavorLoc (cc_ev top_item) $
do { zstack <- mapM zonkCt stack
; env0 <- tcInitTidyEnv
; let zstack_tvs = foldr (unionVarSet . tyVarsOfCt) emptyVarSet zstack
@@ -1079,7 +1078,7 @@ solverDepthErrorTcS depth stack
, ptext (sLit "Use -fcontext-stack=N to increase stack size to N") ]
{- DV: Changing this because Derived's no longer have ids ... Kind of a corner case ...
- = setCtFlavorLoc (cc_flavor top_item) $
+ = setCtFlavorLoc (cc_ev top_item) $
do { ev_vars <- mapM (zonkEvVar . cc_id) stack
; env0 <- tcInitTidyEnv
; let tidy_env = tidyFreeTyVars env0 (tyVarsOfEvVars ev_vars)
@@ -1092,7 +1091,7 @@ solverDepthErrorTcS depth stack
-}
-flattenForAllErrorTcS :: CtFlavor -> TcType -> TcM a
+flattenForAllErrorTcS :: CtEvidence -> TcType -> TcM a
flattenForAllErrorTcS fl ty
= setCtFlavorLoc fl $
do { env0 <- tcInitTidyEnv
@@ -1109,11 +1108,10 @@ flattenForAllErrorTcS fl ty
%************************************************************************
\begin{code}
-setCtFlavorLoc :: CtFlavor -> TcM a -> TcM a
-setCtFlavorLoc (Wanted loc _) thing = setCtLoc loc thing
-setCtFlavorLoc (Derived loc _) thing = setCtLoc loc thing
-setCtFlavorLoc (Given loc _) thing = setCtLoc loc thing
-setCtFlavorLoc (Solved loc _) thing = setCtLoc loc thing
+setCtFlavorLoc :: CtEvidence -> TcM a -> TcM a
+setCtFlavorLoc (Wanted { ctev_wloc = loc }) thing = setCtLoc loc thing
+setCtFlavorLoc (Derived { ctev_wloc = loc }) thing = setCtLoc loc thing
+setCtFlavorLoc (Given { ctev_gloc = loc }) thing = setCtLoc loc thing
\end{code}
%************************************************************************
diff --git a/compiler/typecheck/TcEvidence.lhs b/compiler/typecheck/TcEvidence.lhs
index 8ec0a5766b..09704fbfd1 100644
--- a/compiler/typecheck/TcEvidence.lhs
+++ b/compiler/typecheck/TcEvidence.lhs
@@ -17,7 +17,7 @@ module TcEvidence (
EvBind(..), emptyTcEvBinds, isEmptyTcEvBinds,
EvTerm(..), mkEvCast, evVarsOfTerm, mkEvKindCast,
- EvLit(..),
+ EvLit(..), evTermCoercion,
-- TcCoercion
TcCoercion(..),
@@ -36,7 +36,7 @@ import Var
import PprCore () -- Instance OutputableBndr TyVar
import TypeRep -- Knows type representation
import TcType
-import Type( tyConAppArgN, getEqPredTys_maybe, tyConAppTyCon_maybe )
+import Type( tyConAppArgN, getEqPredTys_maybe, tyConAppTyCon_maybe, getEqPredTys )
import TysPrim( funTyCon )
import TyCon
import PrelNames
@@ -102,6 +102,7 @@ data TcCoercion
| TcSymCo TcCoercion
| TcTransCo TcCoercion TcCoercion
| TcNthCo Int TcCoercion
+ | TcCastCo TcCoercion TcCoercion -- co1 |> co2
| TcLetCo TcEvBinds TcCoercion
deriving (Data.Data, Data.Typeable)
@@ -199,6 +200,8 @@ tcCoercionKind co = go co
where
go (TcRefl ty) = Pair ty ty
go (TcLetCo _ co) = go co
+ go (TcCastCo _ co) = case getEqPredTys (pSnd (go co)) of
+ (ty1,ty2) -> Pair ty1 ty2
go (TcTyConAppCo tc cos) = mkTyConApp tc <$> (sequenceA $ map go cos)
go (TcAppCo co1 co2) = mkAppTy <$> go co1 <*> go co2
go (TcForAllCo tv co) = mkForAllTy tv <$> go co
@@ -206,8 +209,8 @@ tcCoercionKind co = go co
go (TcCoVarCo cv) = eqVarKind cv
go (TcAxiomInstCo ax tys) = Pair (substTyWith (co_ax_tvs ax) tys (co_ax_lhs ax))
(substTyWith (co_ax_tvs ax) tys (co_ax_rhs ax))
- go (TcSymCo co) = swap $ go co
- go (TcTransCo co1 co2) = Pair (pFst $ go co1) (pSnd $ go co2)
+ go (TcSymCo co) = swap (go co)
+ go (TcTransCo co1 co2) = Pair (pFst (go co1)) (pSnd (go co2))
go (TcNthCo d co) = tyConAppArgN d <$> go co
-- c.f. Coercion.coercionKind
@@ -219,7 +222,7 @@ eqVarKind cv
| Just (tc, [_kind,ty1,ty2]) <- tcSplitTyConApp_maybe (varType cv)
= ASSERT (tc `hasKey` eqTyConKey)
Pair ty1 ty2
- | otherwise = panic "eqVarKind, non coercion variable"
+ | otherwise = pprPanic "eqVarKind, non coercion variable" (ppr cv <+> dcolon <+> ppr (varType cv))
coVarsOfTcCo :: TcCoercion -> VarSet
-- Only works on *zonked* coercions, because of TcLetCo
@@ -229,6 +232,7 @@ coVarsOfTcCo tc_co
go (TcRefl _) = emptyVarSet
go (TcTyConAppCo _ cos) = foldr (unionVarSet . go) emptyVarSet cos
go (TcAppCo co1 co2) = go co1 `unionVarSet` go co2
+ go (TcCastCo co1 co2) = go co1 `unionVarSet` go co2
go (TcForAllCo _ co) = go co
go (TcInstCo co _) = go co
go (TcCoVarCo v) = unitVarSet v
@@ -238,7 +242,8 @@ coVarsOfTcCo tc_co
go (TcNthCo _ co) = go co
go (TcLetCo (EvBinds bs) co) = foldrBag (unionVarSet . go_bind) (go co) bs
`minusVarSet` get_bndrs bs
- go (TcLetCo {}) = pprPanic "coVarsOfTcCo called on non-zonked TcCoercion" (ppr tc_co)
+ go (TcLetCo {}) = emptyVarSet -- Harumph. This does legitimately happen in the call
+ -- to evVarsOfTerm in the DEBUG check of setEvBind
-- We expect only coercion bindings
go_bind :: EvBind -> VarSet
@@ -263,7 +268,7 @@ liftTcCoSubstWith tvs cos ty
Nothing -> mkTcReflCo ty
go (AppTy t1 t2) = mkTcAppCo (go t1) (go t2)
go (TyConApp tc tys) = mkTcTyConAppCo tc (map go tys)
- go ty@(LitTy {}) = mkTcReflCo ty
+ go ty@(LitTy {}) = mkTcReflCo ty
go (ForAllTy tv ty) = mkTcForAllCo tv (go ty)
go (FunTy t1 t2) = mkTcFunCo (go t1) (go t2)
\end{code}
@@ -289,6 +294,8 @@ ppr_co p (TcLetCo bs co) = maybeParen p TopPrec $
sep [ptext (sLit "let") <+> braces (ppr bs), ppr co]
ppr_co p (TcAppCo co1 co2) = maybeParen p TyConPrec $
pprTcCo co1 <+> ppr_co TyConPrec co2
+ppr_co p (TcCastCo co1 co2) = maybeParen p FunPrec $
+ ppr_co FunPrec co1 <+> ptext (sLit "|>") <+> ppr_co FunPrec co2
ppr_co p co@(TcForAllCo {}) = ppr_forall_co p co
ppr_co p (TcInstCo co ty) = maybeParen p TyConPrec $
pprParendTcCo co <> ptext (sLit "@") <> pprType ty
@@ -449,29 +456,29 @@ evBindMapBinds bs
data EvBind = EvBind EvVar EvTerm
data EvTerm
- = EvId EvId -- Term-level variable-to-variable bindings
- -- (no coercion variables! they come via EvCoercion)
+ = EvId EvId -- Any sort of evidence Id, including coercions
- | EvCoercion TcCoercion -- (Boxed) coercion bindings
+ | EvCoercion TcCoercion -- (Boxed) coercion bindings
+ -- See Note [Coercion evidence terms]
- | EvCast EvVar TcCoercion -- d |> co
+ | EvCast EvTerm TcCoercion -- d |> co
| EvDFunApp DFunId -- Dictionary instance application
- [Type] [EvVar]
+ [Type] [EvTerm]
- | EvTupleSel EvId Int -- n'th component of the tuple
+ | EvTupleSel EvTerm Int -- n'th component of the tuple, 0-indexed
- | EvTupleMk [EvId] -- tuple built from this stuff
+ | EvTupleMk [EvTerm] -- tuple built from this stuff
| EvDelayedError Type FastString -- Used with Opt_DeferTypeErrors
-- See Note [Deferring coercion errors to runtime]
-- in TcSimplify
- | EvSuperClass DictId Int -- n'th superclass. Used for both equalities and
+ | EvSuperClass EvTerm Int -- n'th superclass. Used for both equalities and
-- dictionaries, even though the former have no
-- selector Id. We count up from _0_
- | EvKindCast EvVar TcCoercion -- See Note [EvKindCast]
+ | EvKindCast EvTerm TcCoercion -- See Note [EvKindCast]
| EvLit EvLit -- Dictionary for class "SingI" for type lits.
-- Note [EvLit]
@@ -486,6 +493,29 @@ data EvLit
\end{code}
+Note [Coecion evidence terms]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Notice that a coercion variable (v :: t1 ~ t2) can be represented as an EvTerm
+in two different ways:
+ EvId v
+ EvCoercion (TcCoVarCo v)
+
+An alternative would be
+
+* To establish the invariant that coercions are represented only
+ by EvCoercion
+
+* To maintain the invariant by smart constructors. Eg
+ mkEvCast (EvCoercion c1) c2 = EvCoercion (TcCastCo c1 c2)
+ mkEvCast t c = EvCast t c
+
+We do quite often need to get a TcCoercion from an EvTerm; see
+'evTermCoercion'. Notice that as well as EvId and EvCoercion it may see
+an EvCast.
+
+I don't think it matters much... but maybe we'll find a good reason to
+do one or the other.
+
Note [EvKindCast]
~~~~~~~~~~~~~~~~~
EvKindCast g kco is produced when we have a constraint (g : s1 ~ s2)
@@ -555,14 +585,14 @@ and another to make it into "SingI" evidence.
\begin{code}
-mkEvCast :: EvVar -> TcCoercion -> EvTerm
+mkEvCast :: EvTerm -> TcCoercion -> EvTerm
mkEvCast ev lco
- | isTcReflCo lco = EvId ev
+ | isTcReflCo lco = ev
| otherwise = EvCast ev lco
-mkEvKindCast :: EvVar -> TcCoercion -> EvTerm
+mkEvKindCast :: EvTerm -> TcCoercion -> EvTerm
mkEvKindCast ev lco
- | isTcReflCo lco = EvId ev
+ | isTcReflCo lco = ev
| otherwise = EvKindCast ev lco
emptyTcEvBinds :: TcEvBinds
@@ -573,17 +603,28 @@ isEmptyTcEvBinds (EvBinds b) = isEmptyBag b
isEmptyTcEvBinds (TcEvBinds {}) = panic "isEmptyTcEvBinds"
-evVarsOfTerm :: EvTerm -> [EvVar]
-evVarsOfTerm (EvId v) = [v]
-evVarsOfTerm (EvCoercion co) = varSetElems (coVarsOfTcCo co)
-evVarsOfTerm (EvDFunApp _ _ evs) = evs
-evVarsOfTerm (EvTupleSel v _) = [v]
-evVarsOfTerm (EvSuperClass v _) = [v]
-evVarsOfTerm (EvCast v co) = v : varSetElems (coVarsOfTcCo co)
-evVarsOfTerm (EvTupleMk evs) = evs
-evVarsOfTerm (EvDelayedError _ _) = []
-evVarsOfTerm (EvKindCast v co) = v : varSetElems (coVarsOfTcCo co)
-evVarsOfTerm (EvLit _) = []
+evTermCoercion :: EvTerm -> TcCoercion
+-- Applied only to EvTerms of type (s~t)
+-- See Note [Coercion evidence terms]
+evTermCoercion (EvId v) = mkTcCoVarCo v
+evTermCoercion (EvCoercion co) = co
+evTermCoercion (EvCast tm co) = TcCastCo (evTermCoercion tm) co
+evTermCoercion tm = pprPanic "evTermCoercion" (ppr tm)
+
+evVarsOfTerm :: EvTerm -> VarSet
+evVarsOfTerm (EvId v) = unitVarSet v
+evVarsOfTerm (EvCoercion co) = coVarsOfTcCo co
+evVarsOfTerm (EvDFunApp _ _ evs) = evVarsOfTerms evs
+evVarsOfTerm (EvTupleSel v _) = evVarsOfTerm v
+evVarsOfTerm (EvSuperClass v _) = evVarsOfTerm v
+evVarsOfTerm (EvCast tm co) = evVarsOfTerm tm `unionVarSet` coVarsOfTcCo co
+evVarsOfTerm (EvTupleMk evs) = evVarsOfTerms evs
+evVarsOfTerm (EvDelayedError _ _) = emptyVarSet
+evVarsOfTerm (EvKindCast v co) = coVarsOfTcCo co `unionVarSet` evVarsOfTerm v
+evVarsOfTerm (EvLit _) = emptyVarSet
+
+evVarsOfTerms :: [EvTerm] -> VarSet
+evVarsOfTerms = foldr (unionVarSet . evVarsOfTerm) emptyVarSet
\end{code}
diff --git a/compiler/typecheck/TcHsSyn.lhs b/compiler/typecheck/TcHsSyn.lhs
index aec09e914d..9104016938 100644
--- a/compiler/typecheck/TcHsSyn.lhs
+++ b/compiler/typecheck/TcHsSyn.lhs
@@ -1095,21 +1095,24 @@ zonkEvTerm env (EvId v) = ASSERT2( isId v, ppr v )
return (EvId (zonkIdOcc env v))
zonkEvTerm env (EvCoercion co) = do { co' <- zonkTcLCoToLCo env co
; return (EvCoercion co') }
-zonkEvTerm env (EvCast v co) = ASSERT( isId v)
- do { co' <- zonkTcLCoToLCo env co
- ; return (mkEvCast (zonkIdOcc env v) co') }
-
-zonkEvTerm env (EvKindCast v co) = ASSERT( isId v)
- do { co' <- zonkTcLCoToLCo env co
- ; return (mkEvKindCast (zonkIdOcc env v) co') }
-
-zonkEvTerm env (EvTupleSel v n) = return (EvTupleSel (zonkIdOcc env v) n)
-zonkEvTerm env (EvTupleMk vs) = return (EvTupleMk (map (zonkIdOcc env) vs))
+zonkEvTerm env (EvCast tm co) = do { tm' <- zonkEvTerm env tm
+ ; co' <- zonkTcLCoToLCo env co
+ ; return (mkEvCast tm' co') }
+
+zonkEvTerm env (EvKindCast v co) = do { v' <- zonkEvTerm env v
+ ; co' <- zonkTcLCoToLCo env co
+ ; return (mkEvKindCast v' co') }
+
+zonkEvTerm env (EvTupleSel tm n) = do { tm' <- zonkEvTerm env tm
+ ; return (EvTupleSel tm' n) }
+zonkEvTerm env (EvTupleMk tms) = do { tms' <- mapM (zonkEvTerm env) tms
+ ; return (EvTupleMk tms') }
zonkEvTerm _ (EvLit l) = return (EvLit l)
-zonkEvTerm env (EvSuperClass d n) = return (EvSuperClass (zonkIdOcc env d) n)
+zonkEvTerm env (EvSuperClass d n) = do { d' <- zonkEvTerm env d
+ ; return (EvSuperClass d' n) }
zonkEvTerm env (EvDFunApp df tys tms)
= do { tys' <- zonkTcTypeToTypes env tys
- ; let tms' = map (zonkEvVarOcc env) tms
+ ; tms' <- mapM (zonkEvTerm env) tms
; return (EvDFunApp (zonkIdOcc env df) tys' tms') }
zonkEvTerm env (EvDelayedError ty msg)
= do { ty' <- zonkTcTypeToType env ty
@@ -1344,6 +1347,8 @@ zonkTcLCoToLCo env co
go (TcAxiomInstCo ax tys) = do { tys' <- zonkTcTypeToTypes env tys; return (TcAxiomInstCo ax tys') }
go (TcAppCo co1 co2) = do { co1' <- go co1; co2' <- go co2
; return (mkTcAppCo co1' co2') }
+ go (TcCastCo co1 co2) = do { co1' <- go co1; co2' <- go co2
+ ; return (TcCastCo co1' co2') }
go (TcSymCo co) = do { co' <- go co; return (mkTcSymCo co') }
go (TcNthCo n co) = do { co' <- go co; return (mkTcNthCo n co') }
go (TcTransCo co1 co2) = do { co1' <- go co1; co2' <- go co2
diff --git a/compiler/typecheck/TcHsType.lhs b/compiler/typecheck/TcHsType.lhs
index 24cd4422c5..b780c3b2e0 100644
--- a/compiler/typecheck/TcHsType.lhs
+++ b/compiler/typecheck/TcHsType.lhs
@@ -783,24 +783,19 @@ then we'd also need
since we only have BOX for a super kind)
\begin{code}
-bindScopedKindVars :: [LHsTyVarBndr Name] -> TcM a -> TcM a
+bindScopedKindVars :: [Name] -> TcM a -> TcM a
-- Given some tyvar binders like [a (b :: k -> *) (c :: k)]
-- bind each scoped kind variable (k in this case) to a fresh
-- kind skolem variable
-bindScopedKindVars hs_tvs thing_inside
- = tcExtendTyVarEnv kvs thing_inside
- where
- kvs :: [KindVar] -- All skolems
- kvs = [ mkKindSigVar kv
- | L _ (KindedTyVar _ (HsBSig _ (_, kvs))) <- hs_tvs
- , kv <- kvs ]
+bindScopedKindVars kvs thing_inside
+ = tcExtendTyVarEnv (map mkKindSigVar kvs) thing_inside
-tcHsTyVarBndrs :: [LHsTyVarBndr Name]
+tcHsTyVarBndrs :: LHsTyVarBndrs Name
-> ([TyVar] -> TcM r)
-> TcM r
-- Bind the type variables to skolems, each with a meta-kind variable kind
-tcHsTyVarBndrs hs_tvs thing_inside
- = bindScopedKindVars hs_tvs $
+tcHsTyVarBndrs (HsQTvs { hsq_kvs = kvs, hsq_tvs = hs_tvs }) thing_inside
+ = bindScopedKindVars kvs $
do { tvs <- mapM tcHsTyVarBndr hs_tvs
; traceTc "tcHsTyVarBndrs" (ppr hs_tvs $$ ppr tvs)
; tcExtendTyVarEnv tvs (thing_inside tvs) }
@@ -825,7 +820,7 @@ tcHsTyVarBndr (L _ hs_tv)
_ -> do
{ kind <- case hs_tv of
UserTyVar {} -> newMetaKindVar
- KindedTyVar _ (HsBSig kind _) -> tcLHsKind kind
+ KindedTyVar _ kind -> tcLHsKind kind
; return (mkTcTyVar name kind (SkolemTv False)) } } }
------------------
@@ -896,11 +891,11 @@ kcLookupKind nm
AGlobal (ATyCon tc) -> return (tyConKind tc)
_ -> pprPanic "kcLookupKind" (ppr tc_ty_thing) }
-kcTyClTyVars :: Name -> [LHsTyVarBndr Name] -> (TcKind -> TcM a) -> TcM a
+kcTyClTyVars :: Name -> LHsTyVarBndrs Name -> (TcKind -> TcM a) -> TcM a
-- Used for the type variables of a type or class decl,
-- when doing the initial kind-check.
-kcTyClTyVars name hs_tvs thing_inside
- = bindScopedKindVars hs_tvs $
+kcTyClTyVars name (HsQTvs { hsq_kvs = kvs, hsq_tvs = hs_tvs }) thing_inside
+ = bindScopedKindVars kvs $
do { tc_kind <- kcLookupKind name
; let (arg_ks, res_k) = splitKindFunTysN (length hs_tvs) tc_kind
-- There should be enough arrows, because
@@ -912,7 +907,7 @@ kcTyClTyVars name hs_tvs thing_inside
kc_tv (L _ (UserTyVar n)) exp_k
= do { check_in_scope n exp_k
; return (n, exp_k) }
- kc_tv (L _ (KindedTyVar n (HsBSig hs_k _))) exp_k
+ kc_tv (L _ (KindedTyVar n hs_k)) exp_k
= do { k <- tcLHsKind hs_k
; _ <- unifyKind k exp_k
; check_in_scope n exp_k
@@ -930,7 +925,7 @@ kcTyClTyVars name hs_tvs thing_inside
Just thing -> pprPanic "check_in_scope" (ppr thing) }
-----------------------
-tcTyClTyVars :: Name -> [LHsTyVarBndr Name] -- LHS of the type or class decl
+tcTyClTyVars :: Name -> LHsTyVarBndrs Name -- LHS of the type or class decl
-> ([TyVar] -> Kind -> TcM a) -> TcM a
-- Used for the type variables of a type or class decl,
-- on the second pass when constructing the final result
@@ -1051,16 +1046,16 @@ Historical note:
\begin{code}
tcHsPatSigType :: UserTypeCtxt
- -> HsBndrSig (LHsType Name) -- The type signature
- -> TcM ( Type -- The signature
- , [(Name, TcTyVar)] ) -- The new bit of type environment, binding
- -- the scoped type variables
+ -> HsWithBndrs (LHsType Name) -- The type signature
+ -> TcM ( Type -- The signature
+ , [(Name, TcTyVar)] ) -- The new bit of type environment, binding
+ -- the scoped type variables
-- Used for type-checking type signatures in
-- (a) patterns e.g f (x::Int) = e
-- (b) result signatures e.g. g x :: Int = e
-- (c) RULE forall bndrs e.g. forall (x::Int). f x = x
-tcHsPatSigType ctxt (HsBSig hs_ty (sig_kvs, sig_tvs))
+tcHsPatSigType ctxt (HsWB { hswb_cts = hs_ty, hswb_kvs = sig_kvs, hswb_tvs = sig_tvs })
= addErrCtxt (pprHsSigCtxt ctxt hs_ty) $
do { kvs <- mapM new_kv sig_kvs
; tvs <- mapM new_tv sig_tvs
@@ -1081,7 +1076,7 @@ tcHsPatSigType ctxt (HsBSig hs_ty (sig_kvs, sig_tvs))
_ -> newSigTyVar name kind -- See Note [Unifying SigTvs]
tcPatSig :: UserTypeCtxt
- -> HsBndrSig (LHsType Name)
+ -> HsWithBndrs (LHsType Name)
-> TcSigmaType
-> TcM (TcType, -- The type to use for "inside" the signature
[(Name, TcTyVar)], -- The new bit of type environment, binding
diff --git a/compiler/typecheck/TcInstDcls.lhs b/compiler/typecheck/TcInstDcls.lhs
index 776689084f..bc217bb041 100644
--- a/compiler/typecheck/TcInstDcls.lhs
+++ b/compiler/typecheck/TcInstDcls.lhs
@@ -840,7 +840,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
mk_sc_ev_term sc
| null inst_tv_tys
, null dfun_ev_vars = EvId sc
- | otherwise = EvDFunApp sc inst_tv_tys dfun_ev_vars
+ | otherwise = EvDFunApp sc inst_tv_tys (map EvId dfun_ev_vars)
inst_tv_tys = mkTyVarTys inst_tyvars
arg_wrapper = mkWpEvVarApps dfun_ev_vars <.> mkWpTyApps inst_tv_tys
@@ -1141,7 +1141,7 @@ tcInstanceMethods dfun_id clas tyvars dfun_ev_vars inst_tys
; self_dict <- newDict clas inst_tys
; let self_ev_bind = EvBind self_dict
- (EvDFunApp dfun_id (mkTyVarTys tyvars) dfun_ev_vars)
+ (EvDFunApp dfun_id (mkTyVarTys tyvars) (map EvId dfun_ev_vars))
; (meth_id, local_meth_sig) <- mkMethIds sig_fn clas tyvars dfun_ev_vars
inst_tys sel_id
diff --git a/compiler/typecheck/TcInteract.lhs b/compiler/typecheck/TcInteract.lhs
index 884331dbcc..44d6a8d01f 100644
--- a/compiler/typecheck/TcInteract.lhs
+++ b/compiler/typecheck/TcInteract.lhs
@@ -31,7 +31,6 @@ import TyCon
import Name
import IParam
-import TysWiredIn ( eqTyCon )
import FunDeps
import TcEvidence
@@ -46,7 +45,6 @@ import Maybes( orElse )
import Bag
import Control.Monad ( foldM )
-import TrieMap
import VarEnv
import qualified Data.Traversable as Traversable
@@ -106,8 +104,11 @@ solveInteractGiven :: GivenLoc -> [EvVar] -> TcS (Bag Implication)
-- if this can happen in practice though.
solveInteractGiven gloc evs
= solveInteractCts (map mk_noncan evs)
- where mk_noncan ev = CNonCanonical { cc_flavor = Given gloc ev
- , cc_depth = 0 }
+ where
+ mk_noncan ev = CNonCanonical { cc_ev = Given { ctev_gloc = gloc
+ , ctev_evtm = EvId ev
+ , ctev_pred = evVarPred ev }
+ , cc_depth = 0 }
-- The main solver loop implements Note [Basic Simplifier Plan]
---------------------------------------------------------------
@@ -229,13 +230,13 @@ thePipeline = [ ("lookup-in-inerts", lookupInInertsStage)
--------------------------------------------------------------------
lookupInInertsStage :: SimplifierStage
lookupInInertsStage ct
- | isWantedCt ct
+ | Wanted { ctev_evar = ev_id, ctev_pred = pred } <- cc_ev ct
= do { is <- getTcSInerts
- ; case lookupInInerts is (ctPred ct) of
- Just ct_cached
- | not (isDerivedCt ct_cached)
- -> setEvBind (ctId ct) (EvId (ctId ct_cached)) >>
- return Stop
+ ; case lookupInInerts is pred of
+ Just ctev
+ | not (isDerived ctev)
+ -> do { setEvBind ev_id (ctEvTerm ctev)
+ ; return Stop }
_ -> continueWith ct }
| otherwise -- I could do something like that for givens
-- as well I suppose but it is not a big deal
@@ -246,7 +247,6 @@ lookupInInertsStage ct
----------------------------------------------------------
canonicalizationStage :: SimplifierStage
canonicalizationStage = TcCanonical.canonicalize
-
\end{code}
*********************************************************************************
@@ -321,7 +321,7 @@ kickOutRewritableInerts ct
; new_ieqs <- {-# SCC "rewriteInertEqsFromInertEq" #-}
rewriteInertEqsFromInertEq (cc_tyvar ct,
- ct_coercion,cc_flavor ct) ieqs
+ ct_coercion,cc_ev ct) ieqs
; let upd_eqs is = is { inert_cans = new_ics }
where ics = inert_cans is
new_ics = ics { inert_eqs = new_ieqs }
@@ -336,7 +336,7 @@ kickOutRewritableInerts ct
; traceTcS "Kick out" (ppr ct $$ ppr wl)
; updWorkListTcS (unionWorkList wl) }
-rewriteInertEqsFromInertEq :: (TcTyVar, TcCoercion, CtFlavor) -- A new substitution
+rewriteInertEqsFromInertEq :: (TcTyVar, TcCoercion, CtEvidence) -- A new substitution
-> TyVarEnv Ct -- All the inert equalities
-> TcS (TyVarEnv Ct) -- The new inert equalities
rewriteInertEqsFromInertEq (subst_tv, _subst_co, subst_fl) ieqs
@@ -366,7 +366,7 @@ rewriteInertEqsFromInertEq (subst_tv, _subst_co, subst_fl) ieqs
| otherwise -- Just keep it there
= return (Just ct)
where
- fl = cc_flavor ct
+ fl = cc_ev ct
kick_out_rewritable :: Ct
-> InertSet
@@ -401,7 +401,7 @@ kick_out_rewritable ct is@(IS { inert_cans =
-- inert_solved, inert_flat_cache and inert_solved_funeqs
-- optimistically. But when we lookup we have to take the
-- subsitution into account
- fl = cc_flavor ct
+ fl = cc_ev ct
tv = cc_tyvar ct
(ips_out, ips_in) = partitionCCanMap rewritable ipmap
@@ -412,7 +412,7 @@ kick_out_rewritable ct is@(IS { inert_cans =
(irs_out, irs_in) = partitionBag rewritable irreds
(fro_out, fro_in) = partitionBag rewritable frozen
- rewritable ct = (fl `canRewrite` cc_flavor ct) &&
+ rewritable ct = (fl `canRewrite` cc_ev ct) &&
(tv `elemVarSet` tyVarsOfCt ct)
-- NB: tyVarsOfCt will return the type
-- variables /and the kind variables/ that are
@@ -461,9 +461,9 @@ data SPSolveResult = SPCantSolve
-- touchable unification variable.
-- See Note [Touchables and givens]
trySpontaneousSolve :: WorkItem -> TcS SPSolveResult
-trySpontaneousSolve workItem@(CTyEqCan { cc_flavor = gw
+trySpontaneousSolve workItem@(CTyEqCan { cc_ev = gw
, cc_tyvar = tv1, cc_rhs = xi, cc_depth = d })
- | isGivenOrSolved gw
+ | isGiven gw
= return SPCantSolve
| Just tv2 <- tcGetTyVar_maybe xi
= do { tch1 <- isTouchableMetaTyVar tv1
@@ -488,7 +488,7 @@ trySpontaneousSolve _ = return SPCantSolve
----------------
trySpontaneousEqOneWay :: SubGoalDepth
- -> CtFlavor -> TcTyVar -> Xi -> TcS SPSolveResult
+ -> CtEvidence -> TcTyVar -> Xi -> TcS SPSolveResult
-- tv is a MetaTyVar, not untouchable
trySpontaneousEqOneWay d gw tv xi
| not (isSigTyVar tv) || isTyVarTy xi
@@ -498,7 +498,7 @@ trySpontaneousEqOneWay d gw tv xi
----------------
trySpontaneousEqTwoWay :: SubGoalDepth
- -> CtFlavor -> TcTyVar -> TcTyVar -> TcS SPSolveResult
+ -> CtEvidence -> TcTyVar -> TcTyVar -> TcS SPSolveResult
-- Both tyvars are *touchable* MetaTyvars so there is only a chance for kind error here
trySpontaneousEqTwoWay d gw tv1 tv2
@@ -585,10 +585,10 @@ unification variables as RHS of type family equations: F xis ~ alpha.
----------------
solveWithIdentity :: SubGoalDepth
- -> CtFlavor -> TcTyVar -> Xi -> TcS SPSolveResult
+ -> CtEvidence -> TcTyVar -> Xi -> TcS SPSolveResult
-- Solve with the identity coercion
-- Precondition: kind(xi) is a sub-kind of kind(tv)
--- Precondition: CtFlavor is Wanted or Derived
+-- Precondition: CtEvidence is Wanted or Derived
-- See [New Wanted Superclass Work] to see why solveWithIdentity
-- must work for Derived as well as Wanted
-- Returns: workItem where
@@ -607,17 +607,18 @@ solveWithIdentity d wd tv xi
-- cf TcUnify.uUnboundKVar
; setWantedTyBind tv xi'
- ; let refl_xi = mkTcReflCo xi'
+ ; let refl_evtm = EvCoercion (mkTcReflCo xi')
+ refl_pred = mkTcEqPred tv_ty xi'
; when (isWanted wd) $
- setEvBind (flav_evar wd) (EvCoercion refl_xi)
+ setEvBind (ctev_evar wd) refl_evtm
- ; ev_given <- newGivenEvVar (mkTcEqPred tv_ty xi')
- (EvCoercion refl_xi) >>= (return . mn_thing)
- ; let given_fl = Given (mkGivenLoc (flav_wloc wd) UnkSkol) ev_given
+ ; let given_fl = Given { ctev_gloc = mkGivenLoc (ctev_wloc wd) UnkSkol
+ , ctev_pred = refl_pred
+ , ctev_evtm = refl_evtm }
; return $
- SPSolved (CTyEqCan { cc_flavor = given_fl
+ SPSolved (CTyEqCan { cc_ev = given_fl
, cc_tyvar = tv, cc_rhs = xi', cc_depth = d }) }
\end{code}
@@ -654,7 +655,7 @@ or, equivalently,
then there is no reaction
\begin{code}
--- Interaction result of WorkItem <~> AtomicInert
+-- Interaction result of WorkItem <~> Ct
data InteractResult
= IRWorkItemConsumed { ir_fire :: String }
@@ -715,8 +716,8 @@ interactWithInertsStage wi
doInteractWithInert :: Ct -> Ct -> TcS InteractResult
-- Identical class constraints.
doInteractWithInert
- inertItem@(CDictCan { cc_flavor = fl1, cc_class = cls1, cc_tyargs = tys1 })
- workItem@(CDictCan { cc_flavor = fl2, cc_class = cls2, cc_tyargs = tys2 })
+ inertItem@(CDictCan { cc_ev = fl1, cc_class = cls1, cc_tyargs = tys1 })
+ workItem@(CDictCan { cc_ev = fl2, cc_class = cls2, cc_tyargs = tys2 })
| cls1 == cls2
= do { let pty1 = mkClassPred cls1 tys1
@@ -728,13 +729,13 @@ doInteractWithInert
, text "workItem = " <+> ppr workItem ])
; any_fundeps
- <- if isGivenOrSolved fl1 && isGivenOrSolved fl2 then return Nothing
+ <- if isGiven fl1 && isGiven fl2 then return Nothing
-- NB: We don't create fds for given (and even solved), have not seen a useful
-- situation for these and even if we did we'd have to be very careful to only
-- create Derived's and not Wanteds.
else do { let fd_eqns = improveFromAnother inert_pred_loc work_item_pred_loc
- ; wloc <- get_workitem_wloc fl2
+ wloc = getWantedLoc fl2
; rewriteWithFunDeps fd_eqns tys2 wloc }
-- See Note [Efficient Orientation], [When improvement happens]
@@ -745,23 +746,18 @@ doInteractWithInert
| otherwise -> irKeepGoing "NOP"
-- Actual Functional Dependencies
- Just (_rewritten_tys2,_cos2,fd_work)
+ Just (_rewritten_tys2, fd_work)
-- Standard thing: create derived fds and keep on going. Importantly we don't
-- throw workitem back in the worklist because this can cause loops. See #5236.
-> do { emitFDWorkAsDerived fd_work (cc_depth workItem)
; irKeepGoing "Cls/Cls (new fundeps)" } -- Just keep going without droping the inert
}
- where get_workitem_wloc (Wanted wl _) = return wl
- get_workitem_wloc (Derived wl _) = return wl
- get_workitem_wloc _ = pprPanic "Unexpected given workitem!" $
- vcat [ text "Work item =" <+> ppr workItem
- , text "Inert item=" <+> ppr inertItem]
-
+
-- Two pieces of irreducible evidence: if their types are *exactly identical*
-- we can rewrite them. We can never improve using this:
-- if we want ty1 :: Constraint and have ty2 :: Constraint it clearly does not
-- mean that (ty1 ~ ty2)
-doInteractWithInert (CIrredEvCan { cc_flavor = ifl, cc_ty = ty1 })
+doInteractWithInert (CIrredEvCan { cc_ev = ifl, cc_ty = ty1 })
workItem@(CIrredEvCan { cc_ty = ty2 })
| ty1 `eqType` ty2
= solveOneFromTheOther "Irred/Irred" ifl workItem
@@ -771,9 +767,9 @@ doInteractWithInert (CIrredEvCan { cc_flavor = ifl, cc_ty = ty1 })
-- that equates the type (this is "improvement").
-- However, we don't actually need the coercion evidence,
-- so we just generate a fresh coercion variable that isn't used anywhere.
-doInteractWithInert (CIPCan { cc_flavor = ifl, cc_ip_nm = nm1, cc_ip_ty = ty1 })
- workItem@(CIPCan { cc_flavor = wfl, cc_ip_nm = nm2, cc_ip_ty = ty2 })
- | nm1 == nm2 && isGivenOrSolved wfl && isGivenOrSolved ifl
+doInteractWithInert (CIPCan { cc_ev = ifl, cc_ip_nm = nm1, cc_ip_ty = ty1 })
+ workItem@(CIPCan { cc_ev = wfl, cc_ip_nm = nm2, cc_ip_ty = ty2 })
+ | nm1 == nm2 && isGiven wfl && isGiven ifl
= -- See Note [Overriding implicit parameters]
-- Dump the inert item, override totally with the new one
-- Do not require type equality
@@ -786,44 +782,43 @@ doInteractWithInert (CIPCan { cc_flavor = ifl, cc_ip_nm = nm1, cc_ip_ty = ty1 })
| nm1 == nm2
= -- See Note [When improvement happens]
- do { mb_eqv <- newWantedEvVar (mkEqPred ty2 ty1)
+ do { mb_eqv <- newWantedEvVar new_wloc (mkEqPred ty2 ty1)
-- co :: ty2 ~ ty1, see Note [Efficient orientation]
; cv <- case mb_eqv of
Fresh eqv ->
do { updWorkListTcS $ extendWorkListEq $
- CNonCanonical { cc_flavor = Wanted new_wloc eqv
+ CNonCanonical { cc_ev = eqv
, cc_depth = cc_depth workItem }
- ; return eqv }
+ ; return (ctEvTerm eqv) }
Cached eqv -> return eqv
; case wfl of
- Wanted {} ->
- let ip_co = mkTcTyConAppCo (ipTyCon nm1) [mkTcCoVarCo cv]
- in do { setEvBind (ctId workItem) $
- mkEvCast (flav_evar ifl) (mkTcSymCo ip_co)
+ Wanted { ctev_evar = ev_id } ->
+ let ip_co = mkTcTyConAppCo (ipTyCon nm1) [evTermCoercion cv]
+ in do { setEvBind ev_id $
+ mkEvCast (ctEvTerm ifl) (mkTcSymCo ip_co)
; irWorkItemConsumed "IP/IP (solved by rewriting)" }
_ -> pprPanic "Unexpected IP constraint" (ppr workItem) }
- where new_wloc
- | Wanted wl _ <- wfl = wl
- | Derived wl _ <- wfl = wl
- | Wanted wl _ <- ifl = wl
- | Derived wl _ <- ifl = wl
- | otherwise = panic "Solve IP: no WantedLoc!"
-
+ where
+ new_wloc | isGiven wfl = getWantedLoc ifl
+ | otherwise = getWantedLoc wfl
-doInteractWithInert ii@(CFunEqCan { cc_flavor = fl1, cc_fun = tc1
+doInteractWithInert ii@(CFunEqCan { cc_ev = fl1, cc_fun = tc1
, cc_tyargs = args1, cc_rhs = xi1, cc_depth = d1 })
- wi@(CFunEqCan { cc_flavor = fl2, cc_fun = tc2
+ wi@(CFunEqCan { cc_ev = fl2, cc_fun = tc2
, cc_tyargs = args2, cc_rhs = xi2, cc_depth = d2 })
+{- ToDo: Check with Dimitrios
| lhss_match
, isSolved fl1 -- Inert is solved and we can simply ignore it
-- when workitem is given/solved
- , isGivenOrSolved fl2
+ , isGiven fl2
= irInertConsumed "FunEq/FunEq"
| lhss_match
, isSolved fl2 -- Workitem is solved and we can ignore it when
-- the inert is given/solved
- , isGivenOrSolved fl1
+ , isGiven fl1
= irWorkItemConsumed "FunEq/FunEq"
+-}
+
| fl1 `canSolve` fl2 && lhss_match
= do { traceTcS "interact with inerts: FunEq/FunEq" $
vcat [ text "workItem =" <+> ppr wi
@@ -836,10 +831,12 @@ doInteractWithInert ii@(CFunEqCan { cc_flavor = fl1, cc_fun = tc1
-- xdecomp : (F args ~ xi2) -> [(xi2 ~ xi1)]
xdecomp x = [EvCoercion (mk_sym_co x `mkTcTransCo` co1)]
- ; xCtFlavor_cache False fl2 [mkTcEqPred xi2 xi1] xev $ what_next d2
+ ; ctevs <- xCtFlavor_cache False fl2 [mkTcEqPred xi2 xi1] xev
-- Why not simply xCtFlavor? See Note [Cache-caused loops]
-- Why not (mkTcEqPred xi1 xi2)? See Note [Efficient orientation]
+ ; add_to_work d2 ctevs
; irWorkItemConsumed "FunEq/FunEq" }
+
| fl2 `canSolve` fl1 && lhss_match
= do { traceTcS "interact with inerts: FunEq/FunEq" $
vcat [ text "workItem =" <+> ppr wi
@@ -847,25 +844,26 @@ doInteractWithInert ii@(CFunEqCan { cc_flavor = fl1, cc_fun = tc1
; let xev = XEvTerm xcomp xdecomp
-- xcomp : [(xi2 ~ xi1)] -> [(F args ~ xi1)]
- xcomp [x] = EvCoercion (co2 `mkTcTransCo` mkTcCoVarCo x)
+ xcomp [x] = EvCoercion (co2 `mkTcTransCo` evTermCoercion x)
xcomp _ = panic "No more goals!"
-- xdecomp : (F args ~ xi1) -> [(xi2 ~ xi1)]
- xdecomp x = [EvCoercion (mkTcSymCo co2 `mkTcTransCo` mkTcCoVarCo x)]
+ xdecomp x = [EvCoercion (mkTcSymCo co2 `mkTcTransCo` evTermCoercion x)]
- ; xCtFlavor_cache False fl1 [mkTcEqPred xi2 xi1] xev $ what_next d1
+ ; ctevs <- xCtFlavor_cache False fl1 [mkTcEqPred xi2 xi1] xev
-- Why not simply xCtFlavor? See Note [Cache-caused loops]
-- Why not (mkTcEqPred xi1 xi2)? See Note [Efficient orientation]
+ ; add_to_work d1 ctevs
; irInertConsumed "FunEq/FunEq"}
where
+ add_to_work d [ctev] = updWorkListTcS $ extendWorkListEq $
+ CNonCanonical {cc_ev = ctev, cc_depth = d}
+ add_to_work _ _ = return ()
+
lhss_match = tc1 == tc2 && eqTypes args1 args2
- what_next d [new_fl]
- = updWorkListTcS $
- extendWorkListEq (CNonCanonical {cc_flavor=new_fl,cc_depth = d})
- what_next _ _ = return ()
- co1 = mkTcCoVarCo $ flav_evar fl1
- co2 = mkTcCoVarCo $ flav_evar fl2
- mk_sym_co x = mkTcSymCo (mkTcCoVarCo x)
+ co1 = evTermCoercion $ ctEvTerm fl1
+ co2 = evTermCoercion $ ctEvTerm fl2
+ mk_sym_co x = mkTcSymCo (evTermCoercion x)
doInteractWithInert _ _ = irKeepGoing "NOP"
@@ -905,7 +903,7 @@ solving.
\begin{code}
solveOneFromTheOther :: String -- Info
- -> CtFlavor -- Inert
+ -> CtEvidence -- Inert
-> Ct -- WorkItem
-> TcS InteractResult
-- Preconditions:
@@ -920,22 +918,23 @@ solveOneFromTheOther info ifl workItem
-- so it's safe to continue on from this point
= irInertConsumed ("Solved[DI] " ++ info)
- | isSolved ifl, isGivenOrSolved wfl
+{- ToDo: Check with Dimitrios
+ | isSolved ifl, isGiven wfl
-- Same if the inert is a GivenSolved -- just get rid of it
= irInertConsumed ("Solved[SI] " ++ info)
+-}
| otherwise
= ASSERT( ifl `canSolve` wfl )
-- Because of Note [The Solver Invariant], plus Derived dealt with
- do { when (isWanted wfl) $ setEvBind wid (EvId iid)
+ do { case wfl of
+ Wanted { ctev_evar = ev_id } -> setEvBind ev_id (ctEvTerm ifl)
+ _ -> return ()
-- Overwrite the binding, if one exists
-- If both are Given, we already have evidence; no need to duplicate
; irWorkItemConsumed ("Solved " ++ info) }
where
- wfl = cc_flavor workItem
- wid = ctId workItem
- iid = flav_evar ifl
-
+ wfl = cc_ev workItem
\end{code}
Note [Superclasses and recursive dictionaries]
@@ -1305,7 +1304,7 @@ now!).
rewriteWithFunDeps :: [Equation]
-> [Xi]
-> WantedLoc
- -> TcS (Maybe ([Xi], [TcCoercion], [(EvVar,WantedLoc)]))
+ -> TcS (Maybe ([Xi], [CtEvidence]))
-- Not quite a WantedEvVar unfortunately
-- Because our intention could be to make
-- it derived at the end of the day
@@ -1313,13 +1312,13 @@ rewriteWithFunDeps :: [Equation]
-- Post: returns no trivial equalities (identities) and all EvVars returned are fresh
rewriteWithFunDeps eqn_pred_locs xis wloc
= do { fd_ev_poss <- mapM (instFunDepEqn wloc) eqn_pred_locs
- ; let fd_ev_pos :: [(Int,(EqVar,WantedLoc))]
+ ; let fd_ev_pos :: [(Int,CtEvidence)]
fd_ev_pos = concat fd_ev_poss
- (rewritten_xis, cos) = unzip (rewriteDictParams fd_ev_pos xis)
+ rewritten_xis = rewriteDictParams fd_ev_pos xis
; if null fd_ev_pos then return Nothing
- else return (Just (rewritten_xis, cos, map snd fd_ev_pos)) }
+ else return (Just (rewritten_xis, map snd fd_ev_pos)) }
-instFunDepEqn :: WantedLoc -> Equation -> TcS [(Int,(EvVar,WantedLoc))]
+instFunDepEqn :: WantedLoc -> Equation -> TcS [(Int,CtEvidence)]
-- Post: Returns the position index as well as the corresponding FunDep equality
instFunDepEqn wl (FDEqn { fd_qtvs = qtvs, fd_eqs = eqs
, fd_pred1 = d1, fd_pred2 = d2 })
@@ -1332,10 +1331,10 @@ instFunDepEqn wl (FDEqn { fd_qtvs = qtvs, fd_eqs = eqs
= let sty1 = Type.substTy subst ty1
sty2 = Type.substTy subst ty2
in if eqType sty1 sty2 then return ievs -- Return no trivial equalities
- else do { mb_eqv <- newWantedEvVar (mkTcEqPred sty1 sty2)
+ else do { mb_eqv <- newDerived (push_ctx wl) (mkTcEqPred sty1 sty2)
; case mb_eqv of
- Fresh eqv -> return $ (i,(eqv, push_ctx wl)):ievs
- Cached {} -> return ievs }
+ Just ctev -> return $ (i,ctev):ievs
+ Nothing -> return ievs }
-- We are eventually going to emit FD work back in the work list so
-- it is important that we only return the /freshly created/ and not
-- some existing equality!
@@ -1355,34 +1354,30 @@ mkEqnMsg (pred1,from1) (pred2,from2) tidy_env
nest 2 (sep [ppr tpred2 <> comma, nest 2 from2])]
; return (tidy_env, msg) }
-rewriteDictParams :: [(Int,(EqVar,WantedLoc))] -- A set of coercions : (pos, ty' ~ ty)
- -> [Type] -- A sequence of types: tys
- -> [(Type, TcCoercion)] -- Returns: [(ty', co : ty' ~ ty)]
+rewriteDictParams :: [(Int,CtEvidence)] -- A set of coercions : (pos, ty' ~ ty)
+ -> [Type] -- A sequence of types: tys
+ -> [Type]
rewriteDictParams param_eqs tys
= zipWith do_one tys [0..]
where
- do_one :: Type -> Int -> (Type, TcCoercion)
+ do_one :: Type -> Int -> Type
do_one ty n = case lookup n param_eqs of
- Just wev -> (get_fst_ty wev, mkTcCoVarCo (fst wev))
- Nothing -> (ty, mkTcReflCo ty) -- Identity
+ Just wev -> get_fst_ty wev
+ Nothing -> ty
- get_fst_ty (wev,_wloc)
- | Just (ty1, _) <- getEqPredTys_maybe (evVarPred wev )
+ get_fst_ty ctev
+ | Just (ty1, _) <- getEqPredTys_maybe (ctEvPred ctev)
= ty1
| otherwise
= panic "rewriteDictParams: non equality fundep!?"
-emitFDWorkAsDerived :: [(EvVar,WantedLoc)]
+emitFDWorkAsDerived :: [CtEvidence] -- All Derived
-> SubGoalDepth -> TcS ()
emitFDWorkAsDerived evlocs d
- = updWorkListTcS $ appendWorkListEqs fd_cts
- where fd_cts = map mk_fd_ct evlocs
- mk_fd_ct (v,wl)
- = CNonCanonical { cc_flavor = Derived wl (evVarPred v)
- , cc_depth = d }
-
-
+ = updWorkListTcS $ appendWorkListEqs (map mk_fd_ct evlocs)
+ where
+ mk_fd_ct der_ev = CNonCanonical { cc_ev = der_ev, cc_depth = d }
\end{code}
@@ -1432,11 +1427,11 @@ doTopReact :: InertSet -> WorkItem -> TcS TopInteractResult
-- Given dictionary
-- See Note [Given constraint that matches an instance declaration]
-doTopReact _inerts (CDictCan { cc_flavor = Given {} })
+doTopReact _inerts (CDictCan { cc_ev = Given {} })
= return NoTopInt -- NB: Superclasses already added since it's canonical
-- Derived dictionary: just look for functional dependencies
-doTopReact _inerts workItem@(CDictCan { cc_flavor = Derived loc _pty
+doTopReact _inerts workItem@(CDictCan { cc_ev = Derived loc _pty
, cc_class = cls, cc_tyargs = xis })
= do { instEnvs <- getInstEnvs
; let fd_eqns = improveFromInstEnv instEnvs
@@ -1444,7 +1439,7 @@ doTopReact _inerts workItem@(CDictCan { cc_flavor = Derived loc _pty
; m <- rewriteWithFunDeps fd_eqns xis loc
; case m of
Nothing -> return NoTopInt
- Just (xis',_,fd_work) ->
+ Just (xis', fd_work) ->
let workItem' = workItem { cc_tyargs = xis' }
-- Deriveds are not supposed to have identity
in do { emitFDWorkAsDerived fd_work (cc_depth workItem)
@@ -1454,7 +1449,7 @@ doTopReact _inerts workItem@(CDictCan { cc_flavor = Derived loc _pty
}
-- Wanted dictionary
-doTopReact inerts workItem@(CDictCan { cc_flavor = fl@(Wanted loc dict_id)
+doTopReact inerts workItem@(CDictCan { cc_ev = fl@(Wanted { ctev_wloc = loc, ctev_evar = dict_id })
, cc_class = cls, cc_tyargs = xis
, cc_depth = depth })
-- See Note [MATCHING-SYNONYMS]
@@ -1470,108 +1465,103 @@ doTopReact inerts workItem@(CDictCan { cc_flavor = fl@(Wanted loc dict_id)
Nothing ->
do { lkup_inst_res <- matchClassInst inerts cls xis loc
; case lkup_inst_res of
- GenInst wtvs ev_term
- -> let sfl = Solved (mkSolvedLoc loc UnkSkol) dict_id
- in addToSolved (workItem { cc_flavor = sfl }) >>
- doSolveFromInstance wtvs ev_term
- NoInstance
- -> return NoTopInt
+ GenInst wtvs ev_term -> do { addToSolved fl
+ ; doSolveFromInstance wtvs ev_term }
+ NoInstance -> return NoTopInt
}
-- Actual Functional Dependencies
- Just (_xis',_cos,fd_work) ->
+ Just (_xis', fd_work) ->
do { emitFDWorkAsDerived fd_work (cc_depth workItem)
; return SomeTopInt { tir_rule = "Dict/Top (fundeps)"
, tir_new_item = ContinueWith workItem } } }
- where doSolveFromInstance :: [EvVar] -> EvTerm -> TcS TopInteractResult
- -- Precondition: evidence term matches the predicate workItem
- doSolveFromInstance evs ev_term
- | null evs
- = do { traceTcS "doTopReact/found nullary instance for" $
- ppr dict_id
- ; setEvBind dict_id ev_term
- ; return $
- SomeTopInt { tir_rule = "Dict/Top (solved, no new work)"
- , tir_new_item = Stop } }
- | otherwise
- = do { traceTcS "doTopReact/found non-nullary instance for" $
- ppr dict_id
- ; setEvBind dict_id ev_term
- ; let mk_new_wanted ev
- = CNonCanonical { cc_flavor = fl { flav_evar = ev }
- , cc_depth = depth + 1 }
- ; updWorkListTcS (appendWorkListCt (map mk_new_wanted evs))
- ; return $
- SomeTopInt { tir_rule = "Dict/Top (solved, more work)"
- , tir_new_item = Stop }
- }
+ where
+ doSolveFromInstance :: [CtEvidence] -> EvTerm -> TcS TopInteractResult
+ -- Precondition: evidence term matches the predicate workItem
+ doSolveFromInstance evs ev_term
+ | null evs
+ = do { traceTcS "doTopReact/found nullary instance for" $
+ ppr dict_id
+ ; setEvBind dict_id ev_term
+ ; return $
+ SomeTopInt { tir_rule = "Dict/Top (solved, no new work)"
+ , tir_new_item = Stop } }
+ | otherwise
+ = do { traceTcS "doTopReact/found non-nullary instance for" $
+ ppr dict_id
+ ; setEvBind dict_id ev_term
+ ; let mk_new_wanted ev
+ = CNonCanonical { cc_ev = ev
+ , cc_depth = depth + 1 }
+ ; updWorkListTcS (appendWorkListCt (map mk_new_wanted evs))
+ ; return $
+ SomeTopInt { tir_rule = "Dict/Top (solved, more work)"
+ , tir_new_item = Stop }
+ }
-- Type functions
-doTopReact _inerts (CFunEqCan { cc_flavor = fl })
+{- ToDo: Check with Dimitrios
+doTopReact _inerts (CFunEqCan { cc_ev = fl })
| isSolved fl
= return NoTopInt -- If Solved, no more interactions should happen
+-}
-- Otherwise, it's a Given, Derived, or Wanted
-doTopReact _inerts workItem@(CFunEqCan { cc_flavor = fl, cc_depth = d
+doTopReact _inerts workItem@(CFunEqCan { cc_ev = fl, cc_depth = d
, cc_fun = tc, cc_tyargs = args, cc_rhs = xi })
= ASSERT (isSynFamilyTyCon tc) -- No associated data families have reached that far
do { match_res <- matchFam tc args -- See Note [MATCHING-SYNONYMS]
; case match_res of
Nothing -> return NoTopInt
Just (famInst, rep_tys)
- -> do { mb_already_solved <- lkpFunEqCache (mkTyConApp tc args)
+ -> do { mb_already_solved <- lkpSolvedFunEqCache (mkTyConApp tc args)
; traceTcS "doTopReact: Family instance matches" $
vcat [ text "solved-fun-cache" <+> if isJust mb_already_solved then text "hit" else text "miss"
, text "workItem =" <+> ppr workItem ]
; let (coe,rhs_ty)
- | Just cached_ct <- mb_already_solved
- = (mkTcCoVarCo (ctId cached_ct),
- cc_rhs cached_ct)
+ | Just ctev <- mb_already_solved
+ , not (isDerived ctev)
+ = ASSERT( isEqPred (ctEvPred ctev) )
+ (evTermCoercion (ctEvTerm ctev), snd (getEqPredTys (ctEvPred ctev)))
| otherwise
= let coe_ax = famInstAxiom famInst
in (mkTcAxInstCo coe_ax rep_tys,
mkAxInstRHS coe_ax rep_tys)
- xdecomp x = [EvCoercion (mkTcSymCo coe `mkTcTransCo` mkTcCoVarCo x)]
- xcomp [x] = EvCoercion (coe `mkTcTransCo` mkTcCoVarCo x)
+ xdecomp x = [EvCoercion (mkTcSymCo coe `mkTcTransCo` evTermCoercion x)]
+ xcomp [x] = EvCoercion (coe `mkTcTransCo` evTermCoercion x)
xcomp _ = panic "No more goals!"
xev = XEvTerm xcomp xdecomp
- ; xCtFlavor fl [mkTcEqPred rhs_ty xi] xev what_next } }
- where what_next [ct_flav]
- = do { updWorkListTcS $
- extendWorkListEq (CNonCanonical { cc_flavor = ct_flav
- , cc_depth = d+1 })
- ; cache_in_solved fl
- ; return $ SomeTopInt { tir_rule = "Fun/Top"
- , tir_new_item = Stop } }
- what_next _ -- No subgoal (because it's cached)
- = do { cache_in_solved fl
- ; return $ SomeTopInt { tir_rule = "Fun/Top"
- , tir_new_item = Stop } }
-
- cache_in_solved (Derived {}) = return ()
- cache_in_solved (Wanted wl ev) =
- let sfl = Solved (mkSolvedLoc wl UnkSkol) ev
- solved = workItem { cc_flavor = sfl }
- in updFunEqCache solved >> addToSolved solved
- cache_in_solved fl =
- let sfl = Solved (flav_gloc fl) (flav_evar fl)
- solved = workItem { cc_flavor = sfl }
- in updFunEqCache solved >> addToSolved solved
+ ; ctevs <- xCtFlavor fl [mkTcEqPred rhs_ty xi] xev
+ ; case ctevs of
+ [ctev] -> updWorkListTcS $ extendWorkListEq $
+ CNonCanonical { cc_ev = ctev
+ , cc_depth = d+1 }
+ ctevs -> -- No subgoal (because it's cached)
+ ASSERT( null ctevs) return ()
+
+ ; unless (isDerived fl) $
+ do { addSolvedFunEq fl
+ ; addToSolved fl }
+ ; return $ SomeTopInt { tir_rule = "Fun/Top"
+ , tir_new_item = Stop } } }
-- Any other work item does not react with any top-level equations
doTopReact _inerts _workItem = return NoTopInt
-lkpFunEqCache :: TcType -> TcS (Maybe Ct)
-lkpFunEqCache fam_head
+lkpSolvedFunEqCache :: TcType -> TcS (Maybe CtEvidence)
+lkpSolvedFunEqCache fam_head
= do { (_subst,_inscope) <- getInertEqs
; fun_cache <- getTcSInerts >>= (return . inert_solved_funeqs)
; traceTcS "lkpFunEqCache" $ vcat [ text "fam_head =" <+> ppr fam_head
- , text "funeq cache =" <+> pprCtTypeMap (unCtFamHeadMap fun_cache) ]
- ; rewrite_cached $
- lookupTM fam_head (unCtFamHeadMap fun_cache) }
+ , text "funeq cache =" <+> ppr fun_cache ]
+ ; return (lookupFamHead fun_cache fam_head) }
+
+{- ToDo; talk to Dimitrios. I have no idea what is happening here
+
+ ; rewrite_cached (lookupFamHead fun_cache fam_head) }
-- The two different calls do not seem to make a significant difference in
-- terms of hit/miss rate for many memory-critical/performance tests but the
-- latter blows up the space on the heap somehow ... It maybe the niFixTvSubst.
@@ -1579,11 +1569,10 @@ lkpFunEqCache fam_head
-- lookupTypeMap_mod subst cc_rhs fam_head (unCtFamHeadMap fun_cache) }
where rewrite_cached Nothing = return Nothing
- rewrite_cached (Just ct@(CFunEqCan { cc_flavor = fl, cc_depth = d
+ rewrite_cached (Just ct@(CFunEqCan { cc_ev = fl, cc_depth = d
, cc_fun = tc, cc_tyargs = xis
, cc_rhs = xi}))
- = ASSERT (isSolved fl)
- do { (xis_subst,cos) <- flattenMany d FMFullFlatten fl xis
+ = do { (xis_subst,cos) <- flattenMany d FMFullFlatten fl xis
-- cos :: xis_subst ~ xis
; (xi_subst,co) <- flatten d FMFullFlatten fl xi
-- co :: xi_subst ~ xi
@@ -1607,27 +1596,14 @@ lkpFunEqCache fam_head
-> return Nothing -- Strange: cached?
Just fl'
-> return $
- Just (CFunEqCan { cc_flavor = fl'
+ Just (CFunEqCan { cc_ev = fl'
, cc_depth = d
, cc_fun = tc
, cc_tyargs = xis_subst
, cc_rhs = xi_subst }) }
rewrite_cached (Just other_ct)
= pprPanic "lkpFunEqCache:not family equation!" $ ppr other_ct
-
-updFunEqCache :: Ct -> TcS ()
-updFunEqCache fun_eq@(CFunEqCan { cc_fun = tc, cc_tyargs = xis })
- = modifyInertTcS $ \inert -> ((), upd_inert inert)
- where upd_inert inert
- = let slvd = unCtFamHeadMap (inert_solved_funeqs inert)
- in inert { inert_solved_funeqs =
- CtFamHeadMap (alterTM key upd_funeqs slvd) }
- upd_funeqs Nothing = Just fun_eq
- upd_funeqs (Just _ct) = Just fun_eq
- -- Or _ct? depends on which caches more steps of computation
- key = mkTyConApp tc xis
-updFunEqCache other = pprPanic "updFunEqCache:Non family equation" $ ppr other
-
+-}
\end{code}
@@ -1830,7 +1806,7 @@ NB: The desugarer needs be more clever to deal with equalities
\begin{code}
data LookupInstResult
= NoInstance
- | GenInst [EvVar] EvTerm
+ | GenInst [CtEvidence] EvTerm
matchClassInst :: InertSet -> Class -> [Type] -> WantedLoc -> TcS LookupInstResult
@@ -1875,12 +1851,11 @@ matchClassInst inerts clas tys loc
; if null theta then
return (GenInst [] (EvDFunApp dfun_id tys []))
else do
- { evc_vars <- instDFunConstraints theta
- ; let ev_vars = map mn_thing evc_vars
- new_ev_vars = [mn_thing evc | evc <- evc_vars
- , isFresh evc ]
+ { evc_vars <- instDFunConstraints loc theta
+ ; let new_ev_vars = freshGoals evc_vars
-- new_ev_vars are only the real new variables that can be emitted
- ; return $ GenInst new_ev_vars (EvDFunApp dfun_id tys ev_vars) } }
+ dfun_app = EvDFunApp dfun_id tys (getEvTerms evc_vars)
+ ; return $ GenInst new_ev_vars dfun_app } }
}
where
givens_for_this_clas :: Cts
@@ -1892,7 +1867,7 @@ matchClassInst inerts clas tys loc
given_overlap untch = anyBag (matchable untch) givens_for_this_clas
matchable untch (CDictCan { cc_class = clas_g, cc_tyargs = sys
- , cc_flavor = fl })
+ , cc_ev = fl })
| isGiven fl
= ASSERT( clas_g == clas )
case tcUnifyTys (\tv -> if isTouchableMetaTyVar_InRange untch tv &&
diff --git a/compiler/typecheck/TcMType.lhs b/compiler/typecheck/TcMType.lhs
index 3ba80e3b0f..79b6b02950 100644
--- a/compiler/typecheck/TcMType.lhs
+++ b/compiler/typecheck/TcMType.lhs
@@ -627,29 +627,24 @@ zonkWC (WC { wc_flat = flat, wc_impl = implic, wc_insol = insol })
zonkCt :: Ct -> TcM Ct
-- Zonking a Ct conservatively gives back a CNonCanonical
zonkCt ct
- = do { fl' <- zonkFlavor (cc_flavor ct)
+ = do { fl' <- zonkCtEvidence (cc_ev ct)
; return $
- CNonCanonical { cc_flavor = fl'
+ CNonCanonical { cc_ev = fl'
, cc_depth = cc_depth ct } }
zonkCts :: Cts -> TcM Cts
zonkCts = mapBagM zonkCt
-zonkFlavor :: CtFlavor -> TcM CtFlavor
-zonkFlavor (Given loc evar)
+zonkCtEvidence :: CtEvidence -> TcM CtEvidence
+zonkCtEvidence ctev@(Given { ctev_gloc = loc, ctev_pred = pred })
= do { loc' <- zonkGivenLoc loc
- ; evar' <- zonkEvVar evar
- ; return (Given loc' evar') }
-zonkFlavor (Solved loc evar)
- = do { loc' <- zonkGivenLoc loc
- ; evar' <- zonkEvVar evar
- ; return (Solved loc' evar') }
-zonkFlavor (Wanted loc evar)
- = do { evar' <- zonkEvVar evar
- ; return (Wanted loc evar') }
-zonkFlavor (Derived loc pty)
- = do { pty' <- zonkTcType pty
- ; return (Derived loc pty') }
-
+ ; pred' <- zonkTcType pred
+ ; return (ctev { ctev_gloc = loc', ctev_pred = pred'}) }
+zonkCtEvidence ctev@(Wanted { ctev_pred = pred })
+ = do { pred' <- zonkTcType pred
+ ; return (ctev { ctev_pred = pred' }) }
+zonkCtEvidence ctev@(Derived { ctev_pred = pred })
+ = do { pred' <- zonkTcType pred
+ ; return (ctev { ctev_pred = pred' }) }
zonkGivenLoc :: GivenLoc -> TcM GivenLoc
-- GivenLocs may have unification variables inside them!
diff --git a/compiler/typecheck/TcRnDriver.lhs b/compiler/typecheck/TcRnDriver.lhs
index 80c792f85d..95274f0814 100644
--- a/compiler/typecheck/TcRnDriver.lhs
+++ b/compiler/typecheck/TcRnDriver.lhs
@@ -1159,6 +1159,7 @@ setInteractiveContext hsc_env icxt thing_inside
(mkNameSet (concatMap snd con_fields))
-- setting tcg_field_env is necessary to make RecordWildCards work
-- (test: ghci049)
+ , tcg_fix_env = ic_fix_env icxt
}) $
tcExtendGhciEnv visible_tmp_ids $ -- Note [GHCi temporary Ids]
@@ -1171,13 +1172,13 @@ setInteractiveContext hsc_env icxt thing_inside
-- The returned TypecheckedHsExpr is of type IO [ () ], a list of the bound
-- values, coerced to ().
tcRnStmt :: HscEnv -> InteractiveContext -> LStmt RdrName
- -> IO (Messages, Maybe ([Id], LHsExpr Id))
+ -> IO (Messages, Maybe ([Id], LHsExpr Id, FixityEnv))
tcRnStmt hsc_env ictxt rdr_stmt
= initTcPrintErrors hsc_env iNTERACTIVE $
setInteractiveContext hsc_env ictxt $ do {
-- The real work is done here
- (bound_ids, tc_expr) <- tcUserStmt rdr_stmt ;
+ ((bound_ids, tc_expr), fix_env) <- tcUserStmt rdr_stmt ;
zonked_expr <- zonkTopLExpr tc_expr ;
zonked_ids <- zonkTopBndrs bound_ids ;
@@ -1212,7 +1213,7 @@ tcRnStmt hsc_env ictxt rdr_stmt
(vcat [text "Bound Ids" <+> pprWithCommas ppr global_ids,
text "Typechecked expr" <+> ppr zonked_expr]) ;
- return (global_ids, zonked_expr)
+ return (global_ids, zonked_expr, fix_env)
}
where
bad_unboxed id = addErr (sep [ptext (sLit "GHCi can't bind a variable of unlifted type:"),
@@ -1281,7 +1282,7 @@ runPlans (p:ps) = tryTcLIE_ (runPlans ps) p
-- for more details. We do this lifting by trying different ways ('plans') of
-- lifting the code into the IO monad and type checking each plan until one
-- succeeds.
-tcUserStmt :: LStmt RdrName -> TcM PlanResult
+tcUserStmt :: LStmt RdrName -> TcM (PlanResult, FixityEnv)
-- An expression typed at the prompt is treated very specially
tcUserStmt (L loc (ExprStmt expr _ _ _))
@@ -1319,7 +1320,7 @@ tcUserStmt (L loc (ExprStmt expr _ _ _))
-- naked expression. Deferring type errors here is unhelpful because the
-- expression gets evaluated right away anyway. It also would potentially
-- emit two redundant type-error warnings, one from each plan.
- ; unsetDOptM Opt_DeferTypeErrors $ runPlans [
+ ; plan <- unsetDOptM Opt_DeferTypeErrors $ runPlans [
-- Plan A
do { stuff@([it_id], _) <- tcGhciStmts [bind_stmt, print_it]
; it_ty <- zonkTcType (idType it_id)
@@ -1336,14 +1337,17 @@ tcUserStmt (L loc (ExprStmt expr _ _ _))
-- This two-step story is very clunky, alas
do { _ <- checkNoErrs (tcGhciStmts [let_stmt])
--- checkNoErrs defeats the error recovery of let-bindings
- ; tcGhciStmts [let_stmt, print_it] }
- ]}
+ ; tcGhciStmts [let_stmt, print_it] } ]
+
+ ; fix_env <- getFixityEnv
+ ; return (plan, fix_env) }
tcUserStmt rdr_stmt@(L loc _)
- = do { (([rn_stmt], _), fvs) <- checkNoErrs $
- rnStmts GhciStmt [rdr_stmt] $ \_ ->
- return ((), emptyFVs) ;
- -- Don't try to typecheck if the renamer fails!
+ = do { (([rn_stmt], fix_env), fvs) <- checkNoErrs $
+ rnStmts GhciStmt [rdr_stmt] $ \_ -> do
+ fix_env <- getFixityEnv
+ return (fix_env, emptyFVs)
+ -- Don't try to typecheck if the renamer fails!
; traceRn (text "tcRnStmt" <+> vcat [ppr rdr_stmt, ppr rn_stmt, ppr fvs])
; rnDump (ppr rn_stmt) ;
@@ -1363,7 +1367,8 @@ tcUserStmt rdr_stmt@(L loc _)
-- The plans are:
-- [stmt; print v] if one binder and not v::()
-- [stmt] otherwise
- ; runPlans (print_result_plan ++ [tcGhciStmts [gi_stmt]]) }
+ ; plan <- runPlans (print_result_plan ++ [tcGhciStmts [gi_stmt]])
+ ; return (plan, fix_env) }
where
mk_print_result_plan stmt v
= do { stuff@([v_id], _) <- tcGhciStmts [stmt, print_v]
@@ -1430,10 +1435,13 @@ getGhciStepIO = do
let a_tv = mkTcTyVarName fresh_a (fsLit "a")
ghciM = nlHsAppTy (nlHsTyVar ghciTy) (nlHsTyVar a_tv)
ioM = nlHsAppTy (nlHsTyVar ioTyConName) (nlHsTyVar a_tv)
+
+ stepTy :: LHsType Name -- Renamed, so needs all binders in place
stepTy = noLoc $ HsForAllTy Implicit
- ([noLoc $ UserTyVar a_tv])
- (noLoc [])
- (nlHsFunTy ghciM ioM)
+ (HsQTvs { hsq_tvs = [noLoc (UserTyVar a_tv)]
+ , hsq_kvs = [] })
+ (noLoc [])
+ (nlHsFunTy ghciM ioM)
step = noLoc $ ExprWithTySig (nlHsVar ghciStepIoMName) stepTy
return step
diff --git a/compiler/typecheck/TcRnTypes.lhs b/compiler/typecheck/TcRnTypes.lhs
index 6a79b738fd..d17d3e6a10 100644
--- a/compiler/typecheck/TcRnTypes.lhs
+++ b/compiler/typecheck/TcRnTypes.lhs
@@ -55,9 +55,9 @@ module TcRnTypes(
singleCt, extendCts, isEmptyCts, isCTyEqCan, isCFunEqCan,
isCDictCan_Maybe, isCIPCan_Maybe, isCFunEqCan_Maybe,
isCIrredEvCan, isCNonCanonical, isWantedCt, isDerivedCt,
- isGivenCt, isGivenOrSolvedCt,
- ctWantedLoc,
- SubGoalDepth, mkNonCanonical, ctPred, ctFlavPred, ctId, ctFlavId,
+ isGivenCt,
+ ctWantedLoc, ctEvidence,
+ SubGoalDepth, mkNonCanonical, ctPred, ctEvPred, ctEvTerm, ctEvId,
WantedConstraints(..), insolubleWC, emptyWC, isEmptyWC,
andWC, addFlats, addImplics, mkFlatWC,
@@ -70,9 +70,9 @@ module TcRnTypes(
SkolemInfo(..),
- CtFlavor(..), pprFlavorArising,
- mkSolvedLoc, mkGivenLoc,
- isWanted, isGivenOrSolved, isGiven, isSolved,
+ CtEvidence(..), pprFlavorArising,
+ mkGivenLoc,
+ isWanted, isGiven,
isDerived, getWantedLoc, getGivenLoc, canSolve, canRewrite,
-- Pretty printing
@@ -89,7 +89,7 @@ module TcRnTypes(
import HsSyn
import HscTypes
-import TcEvidence( EvBind, EvBindsVar )
+import TcEvidence
import Type
import Class ( Class )
import TyCon ( TyCon )
@@ -850,7 +850,7 @@ type SubGoalDepth = Int -- An ever increasing number used to restrict
data Ct
-- Atomic canonical constraints
= CDictCan { -- e.g. Num xi
- cc_flavor :: CtFlavor,
+ cc_ev :: CtEvidence,
cc_class :: Class,
cc_tyargs :: [Xi],
@@ -860,14 +860,14 @@ data Ct
| CIPCan { -- ?x::tau
-- See note [Canonical implicit parameter constraints].
- cc_flavor :: CtFlavor,
+ cc_ev :: CtEvidence,
cc_ip_nm :: IPName Name,
- cc_ip_ty :: TcTauType, -- Not a Xi! See same not as above
+ cc_ip_ty :: TcTauType, -- Not a Xi! See same not as above
cc_depth :: SubGoalDepth -- See Note [WorkList]
}
| CIrredEvCan { -- These stand for yet-unknown predicates
- cc_flavor :: CtFlavor,
+ cc_ev :: CtEvidence,
cc_ty :: Xi, -- cc_ty is flat hence it may only be of the form (tv xi1 xi2 ... xin)
-- Since, if it were a type constructor application, that'd make the
-- whole constraint a CDictCan, CIPCan, or CTyEqCan. And it can't be
@@ -881,7 +881,7 @@ data Ct
-- * typeKind xi `compatKind` typeKind tv
-- See Note [Spontaneous solving and kind compatibility]
-- * We prefer unification variables on the left *JUST* for efficiency
- cc_flavor :: CtFlavor,
+ cc_ev :: CtEvidence,
cc_tyvar :: TcTyVar,
cc_rhs :: Xi,
@@ -891,7 +891,7 @@ data Ct
| CFunEqCan { -- F xis ~ xi
-- Invariant: * isSynFamilyTyCon cc_fun
-- * typeKind (F xis) `compatKind` typeKind xi
- cc_flavor :: CtFlavor,
+ cc_ev :: CtEvidence,
cc_fun :: TyCon, -- A type function
cc_tyargs :: [Xi], -- Either under-saturated or exactly saturated
cc_rhs :: Xi, -- *never* over-saturated (because if so
@@ -902,18 +902,24 @@ data Ct
}
| CNonCanonical { -- See Note [NonCanonical Semantics]
- cc_flavor :: CtFlavor,
+ cc_ev :: CtEvidence,
cc_depth :: SubGoalDepth
}
\end{code}
\begin{code}
-mkNonCanonical :: CtFlavor -> Ct
-mkNonCanonical flav = CNonCanonical { cc_flavor = flav, cc_depth = 0}
+mkNonCanonical :: CtEvidence -> Ct
+mkNonCanonical flav = CNonCanonical { cc_ev = flav, cc_depth = 0}
+
+ctEvidence :: Ct -> CtEvidence
+ctEvidence = cc_ev
ctPred :: Ct -> PredType
-ctPred (CNonCanonical { cc_flavor = fl }) = ctFlavPred fl
+ctPred ct = ctEvPred (cc_ev ct)
+-- ToDo Check with Dimitrios
+{-
+ctPred (CNonCanonical { cc_ev = fl }) = ctEvPred fl
ctPred (CDictCan { cc_class = cls, cc_tyargs = xis })
= mkClassPred cls xis
ctPred (CTyEqCan { cc_tyvar = tv, cc_rhs = xi })
@@ -923,18 +929,13 @@ ctPred (CFunEqCan { cc_fun = fn, cc_tyargs = xis1, cc_rhs = xi2 })
ctPred (CIPCan { cc_ip_nm = nm, cc_ip_ty = xi })
= mkIPPred nm xi
ctPred (CIrredEvCan { cc_ty = xi }) = xi
-
-
-ctId :: Ct -> EvVar
--- Precondition: not a derived!
-ctId ct = ctFlavId (cc_flavor ct)
-
+-}
\end{code}
%************************************************************************
%* *
- CtFlavor
+ CtEvidence
The "flavor" of a canonical constraint
%* *
%************************************************************************
@@ -942,20 +943,17 @@ ctId ct = ctFlavId (cc_flavor ct)
\begin{code}
ctWantedLoc :: Ct -> WantedLoc
-- Only works for Wanted/Derived
-ctWantedLoc ct = ASSERT2( not (isGivenOrSolved (cc_flavor ct)), ppr ct )
- getWantedLoc (cc_flavor ct)
+ctWantedLoc ct = ASSERT2( not (isGiven (cc_ev ct)), ppr ct )
+ getWantedLoc (cc_ev ct)
isWantedCt :: Ct -> Bool
-isWantedCt = isWanted . cc_flavor
+isWantedCt = isWanted . cc_ev
isGivenCt :: Ct -> Bool
-isGivenCt = isGiven . cc_flavor
+isGivenCt = isGiven . cc_ev
isDerivedCt :: Ct -> Bool
-isDerivedCt = isDerived . cc_flavor
-
-isGivenOrSolvedCt :: Ct -> Bool
-isGivenOrSolvedCt = isGivenOrSolved . cc_flavor
+isDerivedCt = isDerived . cc_ev
isCTyEqCan :: Ct -> Bool
isCTyEqCan (CTyEqCan {}) = True
@@ -989,7 +987,7 @@ isCNonCanonical _ = False
\begin{code}
instance Outputable Ct where
- ppr ct = ppr (cc_flavor ct) <+>
+ ppr ct = ppr (cc_ev ct) <+>
braces (ppr (cc_depth ct)) <+> parens (text ct_sort)
where ct_sort = case ct of
CTyEqCan {} -> "CTyEqCan"
@@ -1229,86 +1227,80 @@ pprWantedsWithLocs wcs
%* *
%************************************************************************
+Note [Evidence field of CtEvidence]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+During constraint solving we never look at the type of ctev_evtm, or
+ctev_evar; instead we look at the cte_pred field. The evtm/evar field
+may be un-zonked.
+
\begin{code}
-data CtFlavor
- = Given { flav_gloc :: GivenLoc, flav_evar :: EvVar }
- -- Trully given, not depending on subgoals
+data CtEvidence -- Rename to CtEvidence
+ = Given { ctev_gloc :: GivenLoc
+ , ctev_pred :: TcPredType
+ , ctev_evtm :: EvTerm } -- See Note [Evidence field of CtEvidence]
+ -- Truly given, not depending on subgoals
-- NB: Spontaneous unifications belong here
-- DV TODOs: (i) Consider caching actual evidence _term_
-- (ii) Revisit Note [Optimizing Spontaneously Solved Coercions]
- | Solved { flav_gloc :: GivenLoc, flav_evar :: EvVar }
- -- Originally wanted, but now we've produced and
- -- bound some partial evidence for this constraint.
- -- NB: Evidence may rely on yet-wanted constraints or other solved or given
-
- | Wanted { flav_wloc :: WantedLoc, flav_evar :: EvVar }
+ | Wanted { ctev_wloc :: WantedLoc
+ , ctev_pred :: TcPredType
+ , ctev_evar :: EvVar } -- See Note [Evidence field of CtEvidence]
-- Wanted goal
- | Derived { flav_wloc :: WantedLoc, flav_der_pty :: TcPredType }
+ | Derived { ctev_wloc :: WantedLoc
+ , ctev_pred :: TcPredType }
-- A goal that we don't really have to solve and can't immediately
- -- rewrite anything other than a derived (there's no evidence variable!)
+ -- rewrite anything other than a derived (there's no evidence!)
-- but if we do manage to solve it may help in solving other goals.
-ctFlavPred :: CtFlavor -> TcPredType
+ctEvPred :: CtEvidence -> TcPredType
-- The predicate of a flavor
-ctFlavPred (Given _ evar) = evVarPred evar
-ctFlavPred (Solved _ evar) = evVarPred evar
-ctFlavPred (Wanted _ evar) = evVarPred evar
-ctFlavPred (Derived { flav_der_pty = pty }) = pty
-
-ctFlavId :: CtFlavor -> EvVar
--- Precondition: can't be derived
-ctFlavId (Derived _ pty)
- = pprPanic "ctFlavId: derived constraint cannot have id" $
- text "pty =" <+> ppr pty
-ctFlavId fl = flav_evar fl
-
-instance Outputable CtFlavor where
+ctEvPred = ctev_pred
+
+ctEvTerm :: CtEvidence -> EvTerm
+ctEvTerm (Given { ctev_evtm = tm }) = tm
+ctEvTerm (Wanted { ctev_evar = ev }) = EvId ev
+ctEvTerm ctev@(Derived {}) = pprPanic "ctEvTerm: derived constraint cannot have id"
+ (ppr ctev)
+
+ctEvId :: CtEvidence -> TcId
+ctEvId (Wanted { ctev_evar = ev }) = ev
+ctEvId ctev = pprPanic "ctEvId:" (ppr ctev)
+
+instance Outputable CtEvidence where
ppr fl = case fl of
- (Given _ evar) -> ptext (sLit "[G]") <+> ppr evar <+> ppr_pty
- (Solved _ evar) -> ptext (sLit "[S]") <+> ppr evar <+> ppr_pty
- (Wanted _ evar) -> ptext (sLit "[W]") <+> ppr evar <+> ppr_pty
- (Derived {}) -> ptext (sLit "[D]") <+> text "_" <+> ppr_pty
- where ppr_pty = dcolon <+> ppr (ctFlavPred fl)
+ Given {} -> ptext (sLit "[G]") <+> ppr (ctev_evtm fl) <+> ppr_pty
+ Wanted {} -> ptext (sLit "[W]") <+> ppr (ctev_evar fl) <+> ppr_pty
+ Derived {} -> ptext (sLit "[D]") <+> text "_" <+> ppr_pty
+ where ppr_pty = dcolon <+> ppr (ctEvPred fl)
-getWantedLoc :: CtFlavor -> WantedLoc
+getWantedLoc :: CtEvidence -> WantedLoc
-- Precondition: Wanted or Derived
-getWantedLoc fl = flav_wloc fl
+getWantedLoc fl = ctev_wloc fl
-getGivenLoc :: CtFlavor -> GivenLoc
--- Precondition: Given or Solved
-getGivenLoc fl = flav_gloc fl
+getGivenLoc :: CtEvidence -> GivenLoc
+-- Precondition: Given
+getGivenLoc fl = ctev_gloc fl
-pprFlavorArising :: CtFlavor -> SDoc
-pprFlavorArising (Given gl _) = pprArisingAt gl
-pprFlavorArising (Solved gl _) = pprArisingAt gl
-pprFlavorArising (Wanted wl _) = pprArisingAt wl
-pprFlavorArising (Derived wl _) = pprArisingAt wl
+pprFlavorArising :: CtEvidence -> SDoc
+pprFlavorArising (Given { ctev_gloc = gl }) = pprArisingAt gl
+pprFlavorArising ctev = pprArisingAt (ctev_wloc ctev)
-isWanted :: CtFlavor -> Bool
+isWanted :: CtEvidence -> Bool
isWanted (Wanted {}) = True
isWanted _ = False
-isGivenOrSolved :: CtFlavor -> Bool
-isGivenOrSolved (Given {}) = True
-isGivenOrSolved (Solved {}) = True
-isGivenOrSolved _ = False
-
-isSolved :: CtFlavor -> Bool
-isSolved (Solved {}) = True
-isSolved _ = False
-
-isGiven :: CtFlavor -> Bool
-isGiven (Given {}) = True
+isGiven :: CtEvidence -> Bool
+isGiven (Given {}) = True
isGiven _ = False
-isDerived :: CtFlavor -> Bool
+isDerived :: CtEvidence -> Bool
isDerived (Derived {}) = True
isDerived _ = False
-canSolve :: CtFlavor -> CtFlavor -> Bool
+canSolve :: CtEvidence -> CtEvidence -> Bool
-- canSolve ctid1 ctid2
-- The constraint ctid1 can be used to solve ctid2
-- "to solve" means a reaction where the active parts of the two constraints match.
@@ -1325,18 +1317,13 @@ canSolve (Wanted {}) (Wanted {}) = True
canSolve (Derived {}) (Derived {}) = True -- Derived can't solve wanted/given
canSolve _ _ = False -- No evidence for a derived, anyway
-canRewrite :: CtFlavor -> CtFlavor -> Bool
+canRewrite :: CtEvidence -> CtEvidence -> Bool
-- canRewrite ct1 ct2
-- The equality constraint ct1 can be used to rewrite inside ct2
canRewrite = canSolve
-
mkGivenLoc :: WantedLoc -> SkolemInfo -> GivenLoc
mkGivenLoc wl sk = setCtLocOrigin wl sk
-
-mkSolvedLoc :: WantedLoc -> SkolemInfo -> GivenLoc
-mkSolvedLoc wl sk = setCtLocOrigin wl sk
-
\end{code}
%************************************************************************
diff --git a/compiler/typecheck/TcSMonad.lhs b/compiler/typecheck/TcSMonad.lhs
index ca7cf88fd1..287783cb88 100644
--- a/compiler/typecheck/TcSMonad.lhs
+++ b/compiler/typecheck/TcSMonad.lhs
@@ -24,15 +24,13 @@ module TcSMonad (
Ct(..), Xi, tyVarsOfCt, tyVarsOfCts, tyVarsOfCDicts,
emitFrozenError,
- isWanted, isGivenOrSolved, isDerived,
- isGivenOrSolvedCt, isGivenCt,
- isWantedCt, isDerivedCt, pprFlavorArising,
+ isWanted, isDerived,
+ isGivenCt, isWantedCt, isDerivedCt, pprFlavorArising,
isFlexiTcsTv,
canRewrite, canSolve,
- mkSolvedLoc, mkGivenLoc,
- ctWantedLoc,
+ mkGivenLoc, ctWantedLoc,
TcS, runTcS, failTcS, panicTcS, traceTcS, -- Basic functionality
traceFireTcS, bumpStepCountTcS, doWithInert,
@@ -42,16 +40,17 @@ module TcSMonad (
SimplContext(..), isInteractive, performDefaulting,
-- Getting and setting the flattening cache
- getFlatCache, updFlatCache, addToSolved,
+ getFlatCache, updFlatCache, addToSolved, addSolvedFunEq,
deferTcSForAllEq,
setEvBind,
XEvTerm(..),
- MaybeNew (..), isFresh,
- xCtFlavor, -- Transform a CtFlavor during a step
+ MaybeNew (..), isFresh, freshGoals, getEvTerms,
+
+ xCtFlavor, -- Transform a CtEvidence during a step
rewriteCtFlavor, -- Specialized version of xCtFlavor for coercions
- newWantedEvVar, newGivenEvVar, instDFunConstraints, newKindConstraint,
+ newWantedEvVar, instDFunConstraints, newKindConstraint,
newDerived,
xCtFlavor_cache, rewriteCtFlavor_cache,
@@ -68,12 +67,14 @@ module TcSMonad (
-- Inerts
InertSet(..), InertCans(..),
getInertEqs, getCtCoercion,
- emptyInert, getTcSInerts, lookupInInerts, updInertSet, extractUnsolved,
+ emptyInert, getTcSInerts, lookupInInerts,
+ extractUnsolved,
extractUnsolvedTcS, modifyInertTcS,
updInertSetTcS, partitionCCanMap, partitionEqMap,
getRelevantCts, extractRelevantInerts,
- CCanMap (..), CtTypeMap, CtFamHeadMap(..), CtPredMap(..),
- pprCtTypeMap, partCtFamHeadMap,
+ CCanMap(..), CtTypeMap, CtFamHeadMap, CtPredMap,
+ PredMap, FamHeadMap,
+ partCtFamHeadMap, lookupFamHead,
instDFunType, -- Instantiation
@@ -136,14 +137,15 @@ import TcRnTypes
import Unique
import UniqFM
-import Maybes ( orElse )
+#ifdef DEBUG
+import Digraph
+#endif
+import Maybes ( orElse, catMaybes )
-import Control.Monad( when )
+import Control.Monad( when, zipWithM )
import StaticFlags( opt_PprStyle_Debug )
import Data.IORef
-import Data.List ( find )
-import Control.Monad ( zipWithM )
import TrieMap
\end{code}
@@ -298,11 +300,10 @@ emptyCCanMap = CCanMap { cts_given = emptyUFM, cts_derived = emptyUFM, cts_wante
updCCanMap:: Uniquable a => (a,Ct) -> CCanMap a -> CCanMap a
updCCanMap (a,ct) cmap
- = case cc_flavor ct of
+ = case cc_ev ct of
Wanted {} -> cmap { cts_wanted = insert_into (cts_wanted cmap) }
Given {} -> cmap { cts_given = insert_into (cts_given cmap) }
Derived {} -> cmap { cts_derived = insert_into (cts_derived cmap) }
- Solved {} -> panic "updCCanMap update with solved!"
where
insert_into m = addToUFM_C unionBags m a (singleCt ct)
@@ -319,13 +320,24 @@ getRelevantCts a cmap
where
lookup map = lookupUFM map a `orElse` emptyCts
-lookupCCanMap :: Uniquable a => a -> (Ct -> Bool) -> CCanMap a -> Maybe Ct
-lookupCCanMap a p map
- = let possible_cts = lookupUFM (cts_given map) a `orElse`
- lookupUFM (cts_wanted map) a `orElse`
- lookupUFM (cts_derived map) a `orElse` emptyCts
- in find p (bagToList possible_cts)
+lookupCCanMap :: Uniquable a => a -> (CtEvidence -> Bool) -> CCanMap a -> Maybe CtEvidence
+lookupCCanMap a pick_me map
+ = findEvidence pick_me possible_cts
+ where
+ possible_cts = lookupUFM (cts_given map) a `plus` (
+ lookupUFM (cts_wanted map) a `plus` (
+ lookupUFM (cts_derived map) a `plus` emptyCts))
+
+ plus Nothing cts2 = cts2
+ plus (Just cts1) cts2 = cts1 `unionBags` cts2
+findEvidence :: (CtEvidence -> Bool) -> Cts -> Maybe CtEvidence
+findEvidence pick_me cts
+ = foldrBag pick Nothing cts
+ where
+ pick :: Ct -> Maybe CtEvidence -> Maybe CtEvidence
+ pick ct deflt | let ctev = cc_ev ct, pick_me ctev = Just ctev
+ | otherwise = deflt
partitionCCanMap :: (Ct -> Bool) -> CCanMap a -> (Cts,CCanMap a)
-- All constraints that /match/ the predicate go in the bag, the rest remain in the map
@@ -360,27 +372,33 @@ extractUnsolvedCMap cmap =
-- Maps from PredTypes to Constraints
-type CtTypeMap = TypeMap Ct
-newtype CtPredMap =
- CtPredMap { unCtPredMap :: CtTypeMap } -- Indexed by TcPredType
-newtype CtFamHeadMap =
- CtFamHeadMap { unCtFamHeadMap :: CtTypeMap } -- Indexed by family head
+type CtTypeMap = TypeMap Ct
+type CtPredMap = PredMap Ct
+type CtFamHeadMap = FamHeadMap Ct
+
+newtype PredMap a = PredMap { unPredMap :: TypeMap a } -- Indexed by TcPredType
+newtype FamHeadMap a = FamHeadMap { unFamHeadMap :: TypeMap a } -- Indexed by family head
-pprCtTypeMap :: TypeMap Ct -> SDoc
-pprCtTypeMap ctmap = ppr (foldTM (:) ctmap [])
+instance Outputable a => Outputable (PredMap a) where
+ ppr (PredMap m) = ppr (foldTM (:) m [])
+
+instance Outputable a => Outputable (FamHeadMap a) where
+ ppr (FamHeadMap m) = ppr (foldTM (:) m [])
ctTypeMapCts :: TypeMap Ct -> Cts
ctTypeMapCts ctmap = foldTM (\ct cts -> extendCts cts ct) ctmap emptyCts
+lookupFamHead :: FamHeadMap a -> TcType -> Maybe a
+lookupFamHead (FamHeadMap m) key = lookupTM key m
partCtFamHeadMap :: (Ct -> Bool)
-> CtFamHeadMap
-> (Cts, CtFamHeadMap)
partCtFamHeadMap f ctmap
= let (cts,tymap_final) = foldTM upd_acc tymap_inside (emptyBag, tymap_inside)
- in (cts, CtFamHeadMap tymap_final)
+ in (cts, FamHeadMap tymap_final)
where
- tymap_inside = unCtFamHeadMap ctmap
+ tymap_inside = unFamHeadMap ctmap
upd_acc ct (cts,acc_map)
| f ct = (extendCts cts ct, alterTM ct_key (\_ -> Nothing) acc_map)
| otherwise = (cts,acc_map)
@@ -388,8 +406,6 @@ partCtFamHeadMap f ctmap
= ty1
| otherwise
= panic "partCtFamHeadMap, encountered non equality!"
-
-
\end{code}
%************************************************************************
@@ -400,9 +416,7 @@ partCtFamHeadMap f ctmap
%************************************************************************
\begin{code}
-
-
--- All Given (fully known) or Wanted or Derived, never Solved
+-- All Given (fully known) or Wanted or Derived
-- See Note [Detailed InertCans Invariants] for more
data InertCans
= IC { inert_eqs :: TyVarEnv Ct
@@ -467,29 +481,51 @@ The InertCans represents a collection of constraints with the following properti
occurs errors.
9 Given family or dictionary constraints don't mention touchable unification variables
-\begin{code}
+
+Note [Solved constraints]
+~~~~~~~~~~~~~~~~~~~~~~~~~
+When we take a step to simplify a constraint 'c', we call the original constraint "solved".
+For example: Wanted: ev :: [s] ~ [t]
+ New goal: ev1 :: s ~ t
+ Then 'ev' is now "solved".
+
+The reason for all this is simply to avoid re-solving goals we have solved already.
+
+* A solved Wanted may depend on as-yet-unsolved goals, so (for example) we should not
+ use it to rewrite a Given; in that sense the solved goal is still a Wanted
+
+* A solved Given is just given
+
+* A solved Derived is possible; purpose is to avoid creating tons of identical
+ Derived goals.
+\begin{code}
-- The Inert Set
data InertSet
= IS { inert_cans :: InertCans
- -- Canonical Given,Wanted,Solved
+ -- Canonical Given, Wanted, Derived (no Solved)
+ -- Sometimes called "the inert set"
+
, inert_frozen :: Cts
-- Frozen errors (as non-canonicals)
- , inert_solved :: CtPredMap
- -- Solved constraints (for caching):
- -- (i) key is by predicate type
- -- (ii) all of 'Solved' flavor, may or may not be canonicals
- -- (iii) we use this field for avoiding creating newEvVars
, inert_flat_cache :: CtFamHeadMap
-- All ``flattening equations'' are kept here.
-- Always canonical CTyFunEqs (Given or Wanted only!)
- -- Key is by family head. We used this field during flattening only
- , inert_solved_funeqs :: CtFamHeadMap
- -- Memoized Solved family equations co :: F xis ~ xi
- -- Stored not necessarily as fully rewritten; we'll do that lazily
- -- when we lookup
+ -- Key is by family head. We use this field during flattening only
+ -- Not necessarily inert wrt top-level equations (or inert_cans)
+
+ , inert_solved_funeqs :: FamHeadMap CtEvidence -- Of form co :: F xis ~ xi
+ , inert_solved :: PredMap CtEvidence -- All others
+ -- These two fields constitute a cache of solved (only!) constraints
+ -- See Note [Solved constraints]
+ -- - Constraints of form (F xis ~ xi) live in inert_solved_funeqs,
+ -- all the others are in inert_solved
+ -- - Used to avoid creating a new EvVar when we have a new goal that we
+ -- have solvedin the past
+ -- - Stored not necessarily as fully rewritten
+ -- (ToDo: rewrite lazily when we lookup)
}
@@ -498,7 +534,7 @@ instance Outputable InertCans where
, vcat (map ppr (Bag.bagToList $ cCanMapToBag (inert_dicts ics)))
, vcat (map ppr (Bag.bagToList $ cCanMapToBag (inert_ips ics)))
, vcat (map ppr (Bag.bagToList $
- ctTypeMapCts (unCtFamHeadMap $ inert_funeqs ics)))
+ ctTypeMapCts (unFamHeadMap $ inert_funeqs ics)))
, vcat (map ppr (Bag.bagToList $ inert_irreds ics))
]
@@ -508,7 +544,7 @@ instance Outputable InertSet where
braces (vcat (map ppr (Bag.bagToList $ inert_frozen is)))
, text "Solved and cached" <+>
int (foldTypeMap (\_ x -> x+1) 0
- (unCtPredMap $ inert_solved is)) <+>
+ (unPredMap $ inert_solved is)) <+>
text "more constraints" ]
emptyInert :: InertSet
@@ -517,28 +553,27 @@ emptyInert
, inert_eq_tvs = emptyInScopeSet
, inert_dicts = emptyCCanMap
, inert_ips = emptyCCanMap
- , inert_funeqs = CtFamHeadMap emptyTM
+ , inert_funeqs = FamHeadMap emptyTM
, inert_irreds = emptyCts }
, inert_frozen = emptyCts
- , inert_flat_cache = CtFamHeadMap emptyTM
- , inert_solved = CtPredMap emptyTM
- , inert_solved_funeqs = CtFamHeadMap emptyTM }
-
-type AtomicInert = Ct
+ , inert_flat_cache = FamHeadMap emptyTM
+ , inert_solved = PredMap emptyTM
+ , inert_solved_funeqs = FamHeadMap emptyTM }
-updInertSet :: InertSet -> AtomicInert -> InertSet
--- Add a new inert element to the inert set.
-updInertSet is item
- | isSolved (cc_flavor item)
- -- Solved items go in their special place
- = let pty = ctPred item
+updSolvedSet :: InertSet -> CtEvidence -> InertSet
+updSolvedSet is item
+ = let pty = ctEvPred item
upd_solved Nothing = Just item
upd_solved (Just _existing_solved) = Just item
-- .. or Just existing_solved? Is this even possible to happen?
in is { inert_solved =
- CtPredMap $
- alterTM pty upd_solved (unCtPredMap $ inert_solved is) }
+ PredMap $
+ alterTM pty upd_solved (unPredMap $ inert_solved is) }
+
+updInertSet :: InertSet -> Ct -> InertSet
+-- Add a new inert element to the inert set.
+updInertSet is item
| isCNonCanonical item
-- NB: this may happen if we decide to kick some frozen error
-- out to rewrite him. Frozen errors are just NonCanonicals
@@ -548,7 +583,7 @@ updInertSet is item
-- A canonical Given, Wanted, or Derived
= is { inert_cans = upd_inert_cans (inert_cans is) item }
- where upd_inert_cans :: InertCans -> AtomicInert -> InertCans
+ where upd_inert_cans :: InertCans -> Ct -> InertCans
-- Precondition: item /is/ canonical
upd_inert_cans ics item
| isCTyEqCan item
@@ -578,14 +613,14 @@ updInertSet is item
upd_funeqs Nothing = Just item
upd_funeqs (Just _already_there)
= panic "updInertSet: item already there!"
- in ics { inert_funeqs = CtFamHeadMap
+ in ics { inert_funeqs = FamHeadMap
(alterTM fam_head upd_funeqs $
- (unCtFamHeadMap $ inert_funeqs ics)) }
+ (unFamHeadMap $ inert_funeqs ics)) }
| otherwise
= pprPanic "upd_inert set: can't happen! Inserting " $
ppr item
-updInertSetTcS :: AtomicInert -> TcS ()
+updInertSetTcS :: Ct -> TcS ()
-- Add a new item in the inerts of the monad
updInertSetTcS item
= do { traceTcS "updInertSetTcs {" $
@@ -596,6 +631,32 @@ updInertSetTcS item
; traceTcS "updInertSetTcs }" $ empty }
+addToSolved :: CtEvidence -> TcS ()
+-- Add a new item in the solved set of the monad
+addToSolved item
+ | isIPPred (ctEvPred item) -- Never cache "solved" implicit parameters (not sure why!)
+ = return ()
+ | otherwise
+ = do { traceTcS "updSolvedSetTcs {" $
+ text "Trying to insert new solved item:" <+> ppr item
+
+ ; modifyInertTcS (\is -> ((), updSolvedSet is item))
+
+ ; traceTcS "updSolvedSetTcs }" $ empty }
+
+addSolvedFunEq :: CtEvidence -> TcS ()
+addSolvedFunEq fun_eq
+ = modifyInertTcS $ \inert -> ((), upd_inert inert)
+ where
+ upd_inert inert
+ = let slvd = unFamHeadMap (inert_solved_funeqs inert)
+ in inert { inert_solved_funeqs =
+ FamHeadMap (alterTM key upd_funeqs slvd) }
+ upd_funeqs Nothing = Just fun_eq
+ upd_funeqs (Just _ct) = Just fun_eq
+ -- Or _ct? depends on which caches more steps of computation
+ key = ctEvPred fun_eq
+
modifyInertTcS :: (InertSet -> (a,InertSet)) -> TcS a
-- Modify the inert set with the supplied function
modifyInertTcS upd
@@ -606,20 +667,10 @@ modifyInertTcS upd
; return a }
-addToSolved :: Ct -> TcS ()
--- Don't do any caching for IP preds because of delicate shadowing
-addToSolved ct
- | isIPPred (ctPred ct)
- = return ()
- | otherwise
- = ASSERT ( isSolved (cc_flavor ct) )
- updInertSetTcS ct
-
extractUnsolvedTcS :: TcS (Cts,Cts)
-- Extracts frozen errors and remaining unsolved and sets the
-- inert set to be the remaining!
-extractUnsolvedTcS =
- modifyInertTcS extractUnsolved
+extractUnsolvedTcS = modifyInertTcS extractUnsolved
extractUnsolved :: InertSet -> ((Cts,Cts), InertSet)
-- Postcondition
@@ -660,22 +711,20 @@ extractUnsolved (IS { inert_cans = IC { inert_eqs = eqs
-- At some point, I used to flush all the solved, in
-- fear of evidence loops. But I think we are safe,
-- flushing is why T3064 had become slower
- , inert_solved = solved -- CtPredMap emptyTM
- , inert_flat_cache = flat_cache -- CtFamHeadMap emptyTM
- , inert_solved_funeqs = funeq_cache -- CtFamHeadMap emptyTM
+ , inert_solved = solved -- PredMap emptyTM
+ , inert_flat_cache = flat_cache -- FamHeadMap emptyTM
+ , inert_solved_funeqs = funeq_cache -- FamHeadMap emptyTM
}
in ((frozen, unsolved), is_solved)
- where solved_eqs = filterVarEnv_Directly (\_ ct -> isGivenOrSolvedCt ct) eqs
+ where solved_eqs = filterVarEnv_Directly (\_ ct -> isGivenCt ct) eqs
unsolved_eqs = foldVarEnv (\ct cts -> cts `extendCts` ct) emptyCts $
eqs `minusVarEnv` solved_eqs
- (unsolved_irreds, solved_irreds) = Bag.partitionBag (not.isGivenOrSolvedCt) irreds
+ (unsolved_irreds, solved_irreds) = Bag.partitionBag (not.isGivenCt) irreds
(unsolved_ips, solved_ips) = extractUnsolvedCMap ips
(unsolved_dicts, solved_dicts) = extractUnsolvedCMap dicts
-
- (unsolved_funeqs, solved_funeqs) =
- partCtFamHeadMap (not . isGivenOrSolved . cc_flavor) funeqs
+ (unsolved_funeqs, solved_funeqs) = partCtFamHeadMap (not . isGivenCt) funeqs
unsolved = unsolved_eqs `unionBags` unsolved_irreds `unionBags`
unsolved_ips `unionBags` unsolved_dicts `unionBags` unsolved_funeqs
@@ -697,7 +746,7 @@ extractRelevantInerts wi
in (cts, ics { inert_dicts = dict_map })
extract_ics_relevants ct@(CFunEqCan {}) ics =
let (cts,feqs_map) =
- let funeq_map = unCtFamHeadMap $ inert_funeqs ics
+ let funeq_map = unFamHeadMap $ inert_funeqs ics
fam_head = mkTyConApp (cc_fun ct) (cc_tyargs ct)
lkp = lookupTM fam_head funeq_map
new_funeq_map = alterTM fam_head xtm funeq_map
@@ -706,7 +755,7 @@ extractRelevantInerts wi
in case lkp of
Nothing -> (emptyCts, funeq_map)
Just ct -> (singleCt ct, new_funeq_map)
- in (cts, ics { inert_funeqs = CtFamHeadMap feqs_map })
+ in (cts, ics { inert_funeqs = FamHeadMap feqs_map })
extract_ics_relevants (CIPCan { cc_ip_nm = nm } ) ics =
let (cts, ips_map) = getRelevantCts nm (inert_ips ics)
in (cts, ics { inert_ips = ips_map })
@@ -716,36 +765,40 @@ extractRelevantInerts wi
extract_ics_relevants _ ics = (emptyCts,ics)
-lookupInInerts :: InertSet -> TcPredType -> Maybe Ct
+lookupInInerts :: InertSet -> TcPredType -> Maybe CtEvidence
-- Is this exact predicate type cached in the solved or canonicals of the InertSet
lookupInInerts (IS { inert_solved = solved, inert_cans = ics }) pty
= case lookupInSolved solved pty of
- Just ct -> return ct
- Nothing -> lookupInInertCans ics pty
+ Just ctev -> return ctev
+ Nothing -> lookupInInertCans ics pty
-lookupInSolved :: CtPredMap -> TcPredType -> Maybe Ct
+lookupInSolved :: PredMap CtEvidence -> TcPredType -> Maybe CtEvidence
-- Returns just if exactly this predicate type exists in the solved.
-lookupInSolved tm pty = lookupTM pty $ unCtPredMap tm
+lookupInSolved tm pty = lookupTM pty $ unPredMap tm
-lookupInInertCans :: InertCans -> TcPredType -> Maybe Ct
+lookupInInertCans :: InertCans -> TcPredType -> Maybe CtEvidence
-- Returns Just if exactly this pred type exists in the inert canonicals
lookupInInertCans ics pty
- = lkp_ics (classifyPredType pty)
- where lkp_ics (ClassPred cls _)
- = lookupCCanMap cls (\ct -> ctPred ct `eqType` pty) (inert_dicts ics)
- lkp_ics (EqPred ty1 _ty2)
- | Just tv <- getTyVar_maybe ty1
- , Just ct <- lookupVarEnv (inert_eqs ics) tv
- , ctPred ct `eqType` pty
- = Just ct
- lkp_ics (EqPred ty1 _ty2) -- Family equation
- | Just _ <- splitTyConApp_maybe ty1
- , Just ct <- lookupTM ty1 (unCtFamHeadMap $ inert_funeqs ics)
- , ctPred ct `eqType` pty
- = Just ct
- lkp_ics (IrredPred {})
- = find (\ct -> ctPred ct `eqType` pty) (bagToList (inert_irreds ics))
- lkp_ics _ = Nothing -- NB: No caching for IPs
+ = case (classifyPredType pty) of
+ ClassPred cls _
+ -> lookupCCanMap cls (\ct -> ctEvPred ct `eqType` pty) (inert_dicts ics)
+
+ EqPred ty1 _ty2
+ | Just tv <- getTyVar_maybe ty1 -- Tyvar equation
+ , Just ct <- lookupVarEnv (inert_eqs ics) tv
+ , let ctev = ctEvidence ct
+ , ctEvPred ctev `eqType` pty
+ -> Just ctev
+
+ | Just _ <- splitTyConApp_maybe ty1 -- Family equation
+ , Just ct <- lookupTM ty1 (unFamHeadMap $ inert_funeqs ics)
+ , let ctev = ctEvidence ct
+ , ctEvPred ctev `eqType` pty
+ -> Just ctev
+
+ IrredPred {} -> findEvidence (\ct -> ctEvPred ct `eqType` pty) (inert_irreds ics)
+
+ _other -> Nothing -- NB: No caching for IPs
\end{code}
@@ -910,10 +963,32 @@ runTcS context untouch is wl tcs
}
-- And return
; ev_binds <- TcM.getTcEvBinds ev_binds_var
+ ; checkForCyclicBinds ev_binds
; return (res, ev_binds) }
where
do_unification (tv,ty) = TcM.writeMetaTyVar tv ty
+checkForCyclicBinds :: Bag EvBind -> TcM ()
+#ifndef DEBUG
+checkForCyclicBinds _ = return ()
+#else
+checkForCyclicBinds ev_binds
+ | null cycles
+ = return ()
+ | null coercion_cycles
+ = TcM.traceTc "Cycle in evidence binds" $ ppr cycles
+ | otherwise
+ = pprPanic "Cycle in coercion bindings" $ ppr coercion_cycles
+ where
+ cycles :: [[EvBind]]
+ cycles = [c | CyclicSCC c <- stronglyConnCompFromEdgedVertices edges]
+
+ coercion_cycles = [c | c <- cycles, any is_co_bind c]
+ is_co_bind (EvBind b _) = isEqVar b
+
+ edges :: [(EvBind, EvVar, [EvVar])]
+ edges = [(bind, bndr, varSetElems (evVarsOfTerm rhs)) | bind@(EvBind bndr rhs) <- bagToList ev_binds]
+#endif
doWithInert :: InertSet -> TcS a -> TcS a
doWithInert inert (TcS action)
@@ -1038,13 +1113,13 @@ emitTcSImplication :: Implication -> TcS ()
emitTcSImplication imp = updTcSImplics (consBag imp)
-emitFrozenError :: CtFlavor -> SubGoalDepth -> TcS ()
+emitFrozenError :: CtEvidence -> SubGoalDepth -> TcS ()
-- Emits a non-canonical constraint that will stand for a frozen error in the inerts.
emitFrozenError fl depth
- = do { traceTcS "Emit frozen error" (ppr (ctFlavPred fl))
+ = do { traceTcS "Emit frozen error" (ppr (ctEvPred fl))
; inert_ref <- getTcSInertsRef
; inerts <- wrapTcS (TcM.readTcRef inert_ref)
- ; let ct = CNonCanonical { cc_flavor = fl
+ ; let ct = CNonCanonical { cc_ev = fl
, cc_depth = depth }
inerts_new = inerts { inert_frozen = extendCts (inert_frozen inerts) ct }
; wrapTcS (TcM.writeTcRef inert_ref inerts_new) }
@@ -1059,24 +1134,23 @@ getTcEvBinds :: TcS EvBindsVar
getTcEvBinds = TcS (return . tcs_ev_binds)
getFlatCache :: TcS CtTypeMap
-getFlatCache = getTcSInerts >>= (return . unCtFamHeadMap . inert_flat_cache)
+getFlatCache = getTcSInerts >>= (return . unFamHeadMap . inert_flat_cache)
updFlatCache :: Ct -> TcS ()
-- Pre: constraint is a flat family equation (equal to a flatten skolem)
-updFlatCache flat_eq@(CFunEqCan { cc_flavor = fl, cc_fun = tc, cc_tyargs = xis })
+updFlatCache flat_eq@(CFunEqCan { cc_ev = fl, cc_fun = tc, cc_tyargs = xis })
= modifyInertTcS upd_inert_cache
- where upd_inert_cache is = ((), is { inert_flat_cache = CtFamHeadMap new_fc })
+ where upd_inert_cache is = ((), is { inert_flat_cache = FamHeadMap new_fc })
where new_fc = alterTM pred_key upd_cache fc
- fc = unCtFamHeadMap $ inert_flat_cache is
+ fc = unFamHeadMap $ inert_flat_cache is
pred_key = mkTyConApp tc xis
- upd_cache (Just ct) | cc_flavor ct `canSolve` fl = Just ct
+ upd_cache (Just ct) | cc_ev ct `canSolve` fl = Just ct
upd_cache (Just _ct) = Just flat_eq
upd_cache Nothing = Just flat_eq
updFlatCache other_ct = pprPanic "updFlatCache: non-family constraint" $
ppr other_ct
-
getUntouchables :: TcS TcsUntouchables
getUntouchables = TcS (return . tcs_untch)
@@ -1296,142 +1370,168 @@ instFlexiTcSHelper tvname tvkind
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
data XEvTerm =
- XEvTerm { ev_comp :: [EvVar] -> EvTerm
+ XEvTerm { ev_comp :: [EvTerm] -> EvTerm
-- How to compose evidence
- , ev_decomp :: EvVar -> [EvTerm]
+ , ev_decomp :: EvTerm -> [EvTerm]
-- How to decompose evidence
}
-data MaybeNew a = Fresh { mn_thing :: a }
- | Cached { mn_thing :: a }
+data MaybeNew = Fresh CtEvidence | Cached EvTerm
-isFresh :: MaybeNew a -> Bool
+isFresh :: MaybeNew -> Bool
isFresh (Fresh {}) = True
isFresh _ = False
-setEvBind :: EvVar -> EvTerm -> TcS ()
-setEvBind ev t
- = do { tc_evbinds <- getTcEvBinds
- ; wrapTcS $ TcM.addTcEvBind tc_evbinds ev t
+getEvTerm :: MaybeNew -> EvTerm
+getEvTerm (Fresh ctev) = ctEvTerm ctev
+getEvTerm (Cached tm) = tm
- ; traceTcS "setEvBind" $ vcat [ text "ev =" <+> ppr ev
- , text "t =" <+> ppr t ]
+getEvTerms :: [MaybeNew] -> [EvTerm]
+getEvTerms = map getEvTerm
-#ifndef DEBUG
- ; return () }
-#else
- ; binds <- getTcEvBindsMap
- ; let cycle = any (reaches binds) (evVarsOfTerm t)
- ; when cycle (fail_if_co_loop binds) }
-
- where fail_if_co_loop binds
- = do { traceTcS "Cycle in evidence binds" $ vcat [ text "evvar =" <+> ppr ev
- , ppr (evBindMapBinds binds) ]
- ; when (isEqVar ev) (pprPanic "setEvBind" (text "BUG: Coercion loop!")) }
-
- reaches :: EvBindMap -> Var -> Bool
- -- Does this evvar reach ev?
- reaches ebm ev0 = go ev0
- where go ev0
- | ev0 == ev = True
- | Just (EvBind _ evtrm) <- lookupEvBind ebm ev0
- = any go (evVarsOfTerm evtrm)
- | otherwise = False
-#endif
+freshGoals :: [MaybeNew] -> [CtEvidence]
+freshGoals mns = [ ctev | Fresh ctev <- mns ]
-newGivenEvVar :: TcPredType -> EvTerm -> TcS (MaybeNew EvVar)
-newGivenEvVar pty evterm
- = do { is <- getTcSInerts
- ; case lookupInInerts is pty of
- Just ct | isGivenOrSolvedCt ct
- -> return (Cached (ctId ct))
- _ -> do { new_ev <- wrapTcS $ TcM.newEvVar pty
- ; setEvBind new_ev evterm
- ; return (Fresh new_ev) } }
-
-newWantedEvVar :: TcPredType -> TcS (MaybeNew EvVar)
-newWantedEvVar pty
+setEvBind :: EvVar -> EvTerm -> TcS ()
+setEvBind the_ev tm
+ = do { traceTcS "setEvBind" $ vcat [ text "ev =" <+> ppr the_ev
+ , text "tm =" <+> ppr tm ]
+ ; tc_evbinds <- getTcEvBinds
+ ; wrapTcS $ TcM.addTcEvBind tc_evbinds the_ev tm }
+
+newGivenEvVar :: GivenLoc -> TcPredType -> EvTerm -> TcS CtEvidence
+-- Make a new variable of the given PredType,
+-- immediately bind it to the given term
+-- and return its CtEvidence
+newGivenEvVar gloc pred rhs
+ = do { new_ev <- wrapTcS $ TcM.newEvVar pred
+ ; setEvBind new_ev rhs
+ ; return (Given { ctev_gloc = gloc, ctev_pred = pred, ctev_evtm = EvId new_ev }) }
+
+newWantedEvVar :: WantedLoc -> TcPredType -> TcS MaybeNew
+newWantedEvVar loc pty
= do { is <- getTcSInerts
; case lookupInInerts is pty of
- Just ct | not (isDerivedCt ct)
- -> do { traceTcS "newWantedEvVar/cache hit" $ ppr ct
- ; return (Cached (ctId ct)) }
+ Just ctev | not (isDerived ctev)
+ -> do { traceTcS "newWantedEvVar/cache hit" $ ppr ctev
+ ; return (Cached (ctEvTerm ctev)) }
_ -> do { new_ev <- wrapTcS $ TcM.newEvVar pty
; traceTcS "newWantedEvVar/cache miss" $ ppr new_ev
- ; return (Fresh new_ev) } }
-
-newDerived :: TcPredType -> TcS (MaybeNew TcPredType)
-newDerived pty
+ ; let ctev = Wanted { ctev_wloc = loc
+ , ctev_pred = pty
+ , ctev_evar = new_ev }
+ ; return (Fresh ctev) } }
+
+newDerived :: WantedLoc -> TcPredType -> TcS (Maybe CtEvidence)
+-- Returns Nothing if cached,
+-- Just pred if not cached
+newDerived loc pty
= do { is <- getTcSInerts
; case lookupInInerts is pty of
- Just {} -> return (Cached pty)
- _ -> return (Fresh pty) }
+ Just {} -> return Nothing
+ _ -> return (Just Derived { ctev_wloc = loc
+ , ctev_pred = pty }) }
-newKindConstraint :: TcTyVar -> Kind -> TcS (MaybeNew EvVar)
+newKindConstraint :: WantedLoc -> TcTyVar -> Kind -> TcS MaybeNew
-- Create new wanted CoVar that constrains the type to have the specified kind.
-newKindConstraint tv knd
+newKindConstraint loc tv knd
= do { ty_k <- wrapTcS (instFlexiTcSHelper (tyVarName tv) knd)
- ; newWantedEvVar (mkTcEqPred (mkTyVarTy tv) ty_k) }
-
-instDFunConstraints :: TcThetaType -> TcS [MaybeNew EvVar]
-instDFunConstraints = mapM newWantedEvVar
+ ; newWantedEvVar loc (mkTcEqPred (mkTyVarTy tv) ty_k) }
+instDFunConstraints :: WantedLoc -> TcThetaType -> TcS [MaybeNew]
+instDFunConstraints wl = mapM (newWantedEvVar wl)
+\end{code}
-xCtFlavor :: CtFlavor -- Original flavor
+
+Note [xCFlavor]
+~~~~~~~~~~~~~~~
+A call might look like this:
+
+ xCtFlavor ev subgoal-preds evidence-transformer
+
+ ev is Given => use ev_decomp to create new Givens for subgoal-preds,
+ and return them
+
+ ev is Wanted => create new wanteds for subgoal-preds,
+ use ev_comp to bind ev,
+ return fresh wanteds (ie ones not cached in inert_cans or solved)
+
+ ev is Derived => create new deriveds for subgoal-preds
+ (unless cached in inert_cans or solved)
+
+Note: The [CtEvidence] returned is a subset of the subgoal-preds passed in
+ Ones that are already cached are not returned
+
+Example
+ ev : Tree a b ~ Tree c d
+ xCtFlavor ev [a~c, b~d] (XEvTerm { ev_comp = \[c1 c2]. <Tree> c1 c2
+ , ev_decomp = \c. [nth 1 c, nth 2 c] })
+ (\fresh-goals. stuff)
+
+\begin{code}
+xCtFlavor :: CtEvidence -- Original flavor
-> [TcPredType] -- New predicate types
-> XEvTerm -- Instructions about how to manipulate evidence
- -> ([CtFlavor] -> TcS a) -- What to do with any remaining /fresh/ goals!
- -> TcS a
+ -> TcS [CtEvidence]
xCtFlavor = xCtFlavor_cache True
-
xCtFlavor_cache :: Bool -- True = if wanted add to the solved bag!
- -> CtFlavor -- Original flavor
+ -> CtEvidence -- Original flavor
-> [TcPredType] -- New predicate types
-> XEvTerm -- Instructions about how to manipulate evidence
- -> ([CtFlavor] -> TcS a) -- What to do with any remaining /fresh/ goals!
- -> TcS a
-xCtFlavor_cache _ (Given { flav_gloc = gl, flav_evar = evar }) ptys xev cont_with
- = do { let ev_trms = ev_decomp xev evar
- ; new_evars <- zipWithM newGivenEvVar ptys ev_trms
- ; cont_with $
- map (\x -> Given gl (mn_thing x)) (filter isFresh new_evars) }
+ -> TcS [CtEvidence]
+
+xCtFlavor_cache _ (Given { ctev_gloc = gl, ctev_evtm = tm }) ptys xev
+ = ASSERT( equalLength ptys (ev_decomp xev tm) )
+ zipWithM (newGivenEvVar gl) ptys (ev_decomp xev tm)
+ -- For Givens we make new EvVars and bind them immediately. We don't worry
+ -- about caching, but we don't expect complicated calculations among Givens.
+ -- It is important to bind each given:
+ -- class (a~b) => C a b where ....
+ -- f :: C a b => ....
+ -- Then in f's Givens we have g:(C a b) and the superclass sc(g,0):a~b.
+ -- But that superclass selector can't (yet) appear in a coercion
+ -- (see evTermCoercion), so the easy thing is to bind it to an Id
-xCtFlavor_cache cache (Wanted { flav_wloc = wl, flav_evar = evar }) ptys xev cont_with
- = do { new_evars <- mapM newWantedEvVar ptys
- ; let evars = map mn_thing new_evars
- evterm = ev_comp xev evars
- ; setEvBind evar evterm
- ; let solved_flav = Solved { flav_gloc = mkSolvedLoc wl UnkSkol
- , flav_evar = evar }
- ; when cache $ addToSolved (mkNonCanonical solved_flav)
- ; cont_with $
- map (\x -> Wanted wl (mn_thing x)) (filter isFresh new_evars) }
-
-xCtFlavor_cache _ (Derived { flav_wloc = wl }) ptys _xev cont_with
- = do { ders <- mapM newDerived ptys
- ; cont_with $
- map (\x -> Derived wl (mn_thing x)) (filter isFresh ders) }
+xCtFlavor_cache cache ctev@(Wanted { ctev_wloc = wl, ctev_evar = evar }) ptys xev
+ = do { new_evars <- mapM (newWantedEvVar wl) ptys
+ ; setEvBind evar (ev_comp xev (getEvTerms new_evars))
+
+ -- Add the now-solved wanted constraint to the cache
+ ; when cache $ addToSolved ctev
+
+ ; return (freshGoals new_evars) }
- -- I am not sure I actually want to do this (e.g. from recanonicalizing a solved?)
- -- but if we plan to use xCtFlavor for rewriting as well then I might as well add a case
-xCtFlavor_cache _ (Solved { flav_gloc = gl, flav_evar = evar }) ptys xev cont_with
- = do { let ev_trms = ev_decomp xev evar
- ; new_evars <- zipWithM newGivenEvVar ptys ev_trms
- ; cont_with $
- map (\x -> Solved gl (mn_thing x)) (filter isFresh new_evars) }
-
-rewriteCtFlavor :: CtFlavor
+xCtFlavor_cache _ (Derived { ctev_wloc = wl }) ptys _xev
+ = do { ders <- mapM (newDerived wl) ptys
+ ; return (catMaybes ders) }
+
+-----------------------------
+rewriteCtFlavor :: CtEvidence
-> TcPredType -- new predicate
-> TcCoercion -- new ~ old
- -> TcS (Maybe CtFlavor)
--- rewriteCtFlavor old_fl new_pred co
--- Main purpose: create a new identity (flavor) for new_pred;
--- unless new_pred is cached already
--- * Returns a new_fl : new_pred, with same wanted/given/derived flag as old_fl
--- * If old_fl was wanted, create a binding for old_fl, in terms of new_fl
--- * If old_fl was given, AND not cached, create a binding for new_fl, in terms of old_fl
--- * Returns Nothing if new_fl is already cached
+ -> TcS (Maybe CtEvidence)
+{-
+ rewriteCtFlavor old_fl new_pred co
+Main purpose: create a new identity (flavor) for new_pred;
+ unless new_pred is cached already
+* Returns a new_fl : new_pred, with same wanted/given/derived flag as old_fl
+* If old_fl was wanted, create a binding for old_fl, in terms of new_fl
+* If old_fl was given, AND not cached, create a binding for new_fl, in terms of old_fl
+* Returns Nothing if new_fl is already cached
+
+
+ Old evidence New predicate is Return new evidence
+ flavour of same flavor
+ -------------------------------------------------------------------
+ Wanted Already solved or in inert Nothing
+ or Derived Not Just new_evidence
+
+ Given Already in inert Nothing
+ Not Just new_evidence
+
+ Solved NEVER HAPPENS
+-}
rewriteCtFlavor = rewriteCtFlavor_cache True
-- Returns Just new_fl iff either (i) 'co' is reflexivity
@@ -1439,40 +1539,40 @@ rewriteCtFlavor = rewriteCtFlavor_cache True
-- In either case, there is nothing new to do with new_fl
rewriteCtFlavor_cache :: Bool
- -> CtFlavor
+ -> CtEvidence
-> TcPredType -- new predicate
-> TcCoercion -- new ~ old
- -> TcS (Maybe CtFlavor)
+ -> TcS (Maybe CtEvidence)
-- If derived, don't even look at the coercion
-- NB: this allows us to sneak away with ``error'' thunks for
-- coercions that come from derived ids (which don't exist!)
-rewriteCtFlavor_cache _cache (Derived wl _pty_orig) pty_new _co
- = newDerived pty_new >>= from_mn
- where from_mn (Cached {}) = return Nothing
- from_mn (Fresh {}) = return $ Just (Derived wl pty_new)
+rewriteCtFlavor_cache _cache (Derived { ctev_wloc = wl }) pty_new _co
+ = newDerived wl pty_new
-rewriteCtFlavor_cache cache fl pty co
- | isTcReflCo co
- -- If just reflexivity then you may re-use the same variable as optimization
- = if ctFlavPred fl `eqType` pty then
- -- E.g. for type synonyms we want to use the original type
- -- since it's not flattened to report better error messages.
- return $ Just fl
- else
- -- E.g. because we rewrite with a spontaneously solved one
- return (Just $ case fl of
- Derived wl _pty_orig -> Derived wl pty
- Given gl ev -> Given gl (setVarType ev pty)
- Wanted wl ev -> Wanted wl (setVarType ev pty)
- Solved gl ev -> Solved gl (setVarType ev pty))
- | otherwise
- = xCtFlavor_cache cache fl [pty] (XEvTerm ev_comp ev_decomp) cont
- where ev_comp [x] = mkEvCast x co
- ev_comp _ = panic "Coercion can only have one subgoal"
- ev_decomp x = [mkEvCast x (mkTcSymCo co)]
- cont [] = return Nothing
- cont [fl] = return $ Just fl
- cont _ = panic "At most one constraint can be subgoal of coercion!"
+rewriteCtFlavor_cache _cache (Given { ctev_gloc = gl, ctev_evtm = old_tm }) pty_new co
+ = return (Just (Given { ctev_gloc = gl, ctev_pred = pty_new, ctev_evtm = new_tm }))
+ where
+ new_tm = mkEvCast old_tm (mkTcSymCo co) -- mkEvCase optimises ReflCo
+
+rewriteCtFlavor_cache cache ctev@(Wanted { ctev_wloc = wl, ctev_evar = evar, ctev_pred = pty_old }) pty_new co
+ | isTcReflCo co -- If just reflexivity then you may re-use the same variable
+ = return (Just (if pty_old `eqType` pty_new
+ then ctev
+ else ctev { ctev_pred = pty_new }))
+ -- If the old and new types compare equal (eqType looks through synonyms)
+ -- then retain the old type, so that error messages come out mentioning synonyms
+
+ | otherwise
+ = do { new_evar <- newWantedEvVar wl pty_new
+ ; setEvBind evar (mkEvCast (getEvTerm new_evar) co)
+
+ -- Add the now-solved wanted constraint to the cache
+ ; when cache $ addToSolved ctev
+
+ ; case new_evar of
+ Fresh ctev -> return (Just ctev)
+ _ -> return Nothing }
+
-- Matching and looking up classes and family instances
@@ -1537,29 +1637,29 @@ deferTcSForAllEq (loc,orig_ev) (tvs1,body1) (tvs2,body2)
phi1 = Type.substTy subst1 body1
phi2 = Type.substTy (zipTopTvSubst tvs2 tys) body2
skol_info = UnifyForAllSkol skol_tvs phi1
- ; mev <- newWantedEvVar (mkTcEqPred phi1 phi2)
- ; let new_fl = Wanted loc (mn_thing mev)
- new_ct = mkNonCanonical new_fl
- new_co = mkTcCoVarCo (mn_thing mev)
- ; coe_inside <- if isFresh mev then
- do { ev_binds_var <- wrapTcS $ TcM.newTcEvBinds
- ; let ev_binds = TcEvBinds ev_binds_var
- ; lcl_env <- wrapTcS $ TcM.getLclTypeEnv
- ; loc <- wrapTcS $ TcM.getCtLoc skol_info
- ; let wc = WC { wc_flat = singleCt new_ct
- , wc_impl = emptyBag
- , wc_insol = emptyCts }
- imp = Implic { ic_untch = all_untouchables
- , ic_env = lcl_env
- , ic_skols = skol_tvs
- , ic_given = []
- , ic_wanted = wc
- , ic_insol = False
- , ic_binds = ev_binds_var
- , ic_loc = loc }
- ; updTcSImplics (consBag imp)
- ; return (TcLetCo ev_binds new_co) }
- else (return new_co)
+ ; mev <- newWantedEvVar loc (mkTcEqPred phi1 phi2)
+ ; coe_inside <- case mev of
+ Cached ev_tm -> return (evTermCoercion ev_tm)
+ Fresh ctev -> do { ev_binds_var <- wrapTcS $ TcM.newTcEvBinds
+ ; let ev_binds = TcEvBinds ev_binds_var
+ new_ct = mkNonCanonical ctev
+ new_co = evTermCoercion (ctEvTerm ctev)
+ ; lcl_env <- wrapTcS $ TcM.getLclTypeEnv
+ ; loc <- wrapTcS $ TcM.getCtLoc skol_info
+ ; let wc = WC { wc_flat = singleCt new_ct
+ , wc_impl = emptyBag
+ , wc_insol = emptyCts }
+ imp = Implic { ic_untch = all_untouchables
+ , ic_env = lcl_env
+ , ic_skols = skol_tvs
+ , ic_given = []
+ , ic_wanted = wc
+ , ic_insol = False
+ , ic_binds = ev_binds_var
+ , ic_loc = loc }
+ ; updTcSImplics (consBag imp)
+ ; return (TcLetCo ev_binds new_co) }
+
; setEvBind orig_ev $
EvCoercion (foldr mkTcForAllCo coe_inside skol_tvs)
}
@@ -1573,7 +1673,6 @@ deferTcSForAllEq (loc,orig_ev) (tvs1,body1) (tvs2,body2)
-- Rewriting with respect to the inert equalities
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\begin{code}
-
getInertEqs :: TcS (TyVarEnv Ct, InScopeSet)
getInertEqs = do { inert <- getTcSInerts
; let ics = inert_cans inert
@@ -1581,11 +1680,15 @@ getInertEqs = do { inert <- getTcSInerts
getCtCoercion :: EvBindMap -> Ct -> TcCoercion
-- Precondition: A CTyEqCan which is either Wanted or Given, never Derived or Solved!
-getCtCoercion bs ct
+getCtCoercion _bs ct
+ = ASSERT( not (isDerivedCt ct) )
+ evTermCoercion (ctEvTerm (ctEvidence ct))
+{- ToDo: check with Dimitrios that we can dump this stuff
+ WARNING: if we *do* need this stuff, we need to think again about cyclic bindings.
= case lookupEvBind bs cc_id of
-- Given and bound to a coercion term
Just (EvBind _ (EvCoercion co)) -> co
- -- NB: The constraint could have been rewritten due to spontaneous
+ -- NB: The constraint could have been rewritten due to spontaneous
-- unifications but because we are optimizing away mkRefls the evidence
-- variable may still have type (alpha ~ [beta]). The constraint may
-- however have a more accurate type (alpha ~ [Int]) (where beta ~ Int has
@@ -1596,6 +1699,9 @@ getCtCoercion bs ct
_ -> mkTcCoVarCo (setVarType cc_id (ctPred ct))
- where cc_id = ctId ct
-
+ where
+ cc_id = ctId ct
+-}
\end{code}
+
+
diff --git a/compiler/typecheck/TcSimplify.lhs b/compiler/typecheck/TcSimplify.lhs
index e6a4fd2f79..f97347a305 100644
--- a/compiler/typecheck/TcSimplify.lhs
+++ b/compiler/typecheck/TcSimplify.lhs
@@ -558,7 +558,7 @@ simplifyRule name lhs_wanted rhs_wanted
-- variables; hence NoUntouchables
; (resid_wanted, _) <- runTcS (SimplInfer doc) untch emptyInert emptyWorkList $
- solveWanteds zonked_all
+ solveWanteds zonked_all
; zonked_lhs <- zonkWC lhs_wanted
@@ -579,7 +579,8 @@ simplifyRule name lhs_wanted rhs_wanted
vcat [ text "zonked_lhs" <+> ppr zonked_lhs
, text "q_cts" <+> ppr q_cts ]
- ; return (map ctId (bagToList q_cts), zonked_lhs { wc_flat = non_q_cts }) }
+ ; return ( map (ctEvId . ctEvidence) (bagToList q_cts)
+ , zonked_lhs { wc_flat = non_q_cts }) }
\end{code}
@@ -784,10 +785,11 @@ solveNestedImplications implics
where givens_from_wanteds = foldrBag get_wanted []
get_wanted cc rest_givens
| pushable_wanted cc
- = let fl = cc_flavor cc
- wloc = flav_wloc fl
- gfl = Given (mkGivenLoc wloc UnkSkol) (flav_evar fl)
- this_given = cc { cc_flavor = gfl }
+ = let fl = ctEvidence cc
+ gfl = Given { ctev_gloc = setCtLocOrigin (ctev_wloc fl) UnkSkol
+ , ctev_evtm = EvId (ctev_evar fl)
+ , ctev_pred = ctev_pred fl }
+ this_given = cc { cc_ev = gfl }
in this_given : rest_givens
| otherwise = rest_givens
@@ -1025,20 +1027,20 @@ solveCTyFunEqs cts
; return (niFixTvSubst ni_subst, unsolved_can_cts) }
where
- solve_one (Wanted _ cv,tv,ty)
+ solve_one (Wanted { ctev_evar = cv }, tv, ty)
= setWantedTyBind tv ty >> setEvBind cv (EvCoercion (mkTcReflCo ty))
solve_one (Derived {}, tv, ty)
= setWantedTyBind tv ty
solve_one arg
= pprPanic "solveCTyFunEqs: can't solve a /given/ family equation!" $ ppr arg
------------
-type FunEqBinds = (TvSubstEnv, [(CtFlavor, TcTyVar, TcType)])
+type FunEqBinds = (TvSubstEnv, [(CtEvidence, TcTyVar, TcType)])
-- The TvSubstEnv is not idempotent, but is loop-free
-- See Note [Non-idempotent substitution] in Unify
emptyFunEqBinds :: FunEqBinds
emptyFunEqBinds = (emptyVarEnv, [])
-extendFunEqBinds :: FunEqBinds -> CtFlavor -> TcTyVar -> TcType -> FunEqBinds
+extendFunEqBinds :: FunEqBinds -> CtEvidence -> TcTyVar -> TcType -> FunEqBinds
extendFunEqBinds (tv_subst, cv_binds) fl tv ty
= (extendVarEnv tv_subst tv ty, (fl, tv, ty):cv_binds)
@@ -1052,7 +1054,7 @@ getSolvableCTyFunEqs untch cts
dflt_funeq :: (Cts, FunEqBinds) -> Ct
-> (Cts, FunEqBinds)
dflt_funeq (cts_in, feb@(tv_subst, _))
- (CFunEqCan { cc_flavor = fl
+ (CFunEqCan { cc_ev = fl
, cc_fun = tc
, cc_tyargs = xis
, cc_rhs = xi })
@@ -1071,7 +1073,7 @@ getSolvableCTyFunEqs untch cts
, not (tv `elemVarSet` niSubstTvSet tv_subst (tyVarsOfTypes xis))
-- Occurs check: see Note [Solving Family Equations], Point 2
- = ASSERT ( not (isGivenOrSolved fl) )
+ = ASSERT ( not (isGiven fl) )
(cts_in, extendFunEqBinds feb fl tv (mkTyConApp tc xis))
dflt_funeq (cts_in, fun_eq_binds) ct
@@ -1210,16 +1212,16 @@ defaultTyVar untch the_tv
, not (k `eqKind` default_k)
= tryTcS $ -- Why tryTcS? See Note [tryTcS in defaulting]
do { let loc = CtLoc DefaultOrigin (getSrcSpan the_tv) [] -- Yuk
- ; eqv <- TcSMonad.newKindConstraint the_tv default_k
+ ; eqv <- TcSMonad.newKindConstraint loc the_tv default_k
; case eqv of
Fresh x ->
return $ unitBag $
- CNonCanonical { cc_flavor = Wanted loc x, cc_depth = 0 }
+ CNonCanonical { cc_ev = x, cc_depth = 0 }
Cached _ -> return emptyBag }
{- DELETEME
if isNewEvVar eqv then
return $ unitBag (CNonCanonical { cc_id = evc_the_evvar eqv
- , cc_flavor = fl, cc_depth = 0 })
+ , cc_ev = fl, cc_depth = 0 })
else return emptyBag }
-}
@@ -1300,13 +1302,12 @@ disambigGroup (default_ty:default_tys) group
; success <- tryTcS $ -- Why tryTcS? See Note [tryTcS in defaulting]
do { derived_eq <- tryTcS $
-- I need a new tryTcS because we will call solveInteractCts below!
- do { md <- newDerived (mkTcEqPred (mkTyVarTy the_tv) default_ty)
+ do { md <- newDerived (ctev_wloc the_fl)
+ (mkTcEqPred (mkTyVarTy the_tv) default_ty)
+ -- ctev_wloc because constraint is not Given!
; case md of
- Cached _ -> return []
- Fresh pty ->
- -- flav_wloc because constraint is not Given/Solved!
- let dfl = Derived (flav_wloc the_fl) pty
- in return [ CNonCanonical { cc_flavor = dfl, cc_depth = 0 } ] }
+ Nothing -> return []
+ Just ctev -> return [ mkNonCanonical ctev ] }
; traceTcS "disambigGroup (solving) {"
(text "trying to solve constraints along with default equations ...")
@@ -1335,7 +1336,7 @@ disambigGroup (default_ty:default_tys) group
; disambigGroup default_tys group } }
where
((the_ct,the_tv):_) = group
- the_fl = cc_flavor the_ct
+ the_fl = cc_ev the_ct
wanteds = map fst group
\end{code}
@@ -1365,9 +1366,12 @@ newFlatWanteds :: CtOrigin -> ThetaType -> TcM [Ct]
newFlatWanteds orig theta
= do { loc <- getCtLoc orig
; mapM (inst_to_wanted loc) theta }
- where inst_to_wanted loc pty
+ where
+ inst_to_wanted loc pty
= do { v <- TcMType.newWantedEvVar pty
; return $
- CNonCanonical { cc_flavor = Wanted loc v
+ CNonCanonical { cc_ev = Wanted { ctev_evar = v
+ , ctev_wloc = loc
+ , ctev_pred = pty }
, cc_depth = 0 } }
\end{code}
diff --git a/compiler/typecheck/TcTyClsDecls.lhs b/compiler/typecheck/TcTyClsDecls.lhs
index b88029433b..114140c8d1 100644
--- a/compiler/typecheck/TcTyClsDecls.lhs
+++ b/compiler/typecheck/TcTyClsDecls.lhs
@@ -335,9 +335,9 @@ getInitialKinds (L _ decl)
-- data T :: *->* where { ... }
-- with *no* tvs in the HsTyDefn
- get_tvs (TyFamily {tcdTyVars = tvs}) = tvs
- get_tvs (ClassDecl {tcdTyVars = tvs}) = tvs
- get_tvs (TyDecl {tcdTyVars = tvs}) = tvs
+ get_tvs (TyFamily {tcdTyVars = tvs}) = hsQTvBndrs tvs
+ get_tvs (ClassDecl {tcdTyVars = tvs}) = hsQTvBndrs tvs
+ get_tvs (TyDecl {tcdTyVars = tvs}) = hsQTvBndrs tvs
get_tvs (ForeignType {}) = []
----------------
@@ -431,17 +431,13 @@ kcConDecl new_or_data (ConDecl { con_name = name, con_qvars = ex_tvs
; return () }
------------------
-kcResultKind :: Maybe (HsBndrSig (LHsKind Name)) -> Kind -> TcM ()
+kcResultKind :: Maybe (LHsKind Name) -> Kind -> TcM ()
kcResultKind Nothing res_k
= discardResult (unifyKind res_k liftedTypeKind)
-- type family F a
-- defaults to type family F a :: *
-kcResultKind (Just (HsBSig k (ss, ns))) res_k
- = ASSERT( null ss ) -- Parser ensures that
- -- type family F a :: (k :: s)
- -- is illegal
- do { let kvs = map mkKindSigVar ns
- ; k' <- tcExtendTyVarEnv kvs (tcLHsKind k)
+kcResultKind (Just k ) res_k
+ = do { k' <- tcLHsKind k
; discardResult (unifyKind k' res_k) }
\end{code}
@@ -727,7 +723,7 @@ tcSynFamInstDecl _ decl = pprPanic "tcSynFamInstDecl" (ppr decl)
-----------------
tcFamTyPats :: TyCon
- -> HsBndrSig [LHsType Name] -- Patterns
+ -> HsWithBndrs [LHsType Name] -- Patterns
-> (TcKind -> TcM ()) -- Kind checker for RHS
-- result is ignored
-> ([TKVar] -> [TcType] -> Kind -> TcM a)
@@ -743,7 +739,8 @@ tcFamTyPats :: TyCon
-- In that case, the type variable 'a' will *already be in scope*
-- (and, if C is poly-kinded, so will its kind parameter).
-tcFamTyPats fam_tc (HsBSig arg_pats (kvars, tvars)) kind_checker thing_inside
+tcFamTyPats fam_tc (HsWB { hswb_cts = arg_pats, hswb_kvs = kvars, hswb_tvs = tvars })
+ kind_checker thing_inside
= do { -- A family instance must have exactly the same number of type
-- parameters as the family declaration. You can't write
-- type family F a :: * -> *
@@ -756,14 +753,16 @@ tcFamTyPats fam_tc (HsBSig arg_pats (kvars, tvars)) kind_checker thing_inside
-- Instantiate with meta kind vars
; fam_arg_kinds <- mapM (const newMetaKindVar) fam_kvs
+ ; loc <- getSrcSpanM
; let (arg_kinds, res_kind)
= splitKindFunTysN fam_arity $
substKiWith fam_kvs fam_arg_kinds fam_body
+ hs_tvs = HsQTvs { hsq_kvs = kvars
+ , hsq_tvs = userHsTyVarBndrs loc tvars }
-- Kind-check and quantify
-- See Note [Quantifying over family patterns]
- ; typats <- tcExtendTyVarEnv (map mkKindSigVar kvars) $
- tcHsTyVarBndrs (map (noLoc . UserTyVar) tvars) $ \ _ ->
+ ; typats <- tcHsTyVarBndrs hs_tvs $ \ _ ->
do { kind_checker res_kind
; tcHsArgTys (quotes (ppr fam_tc)) arg_pats arg_kinds }
; let all_args = fam_arg_kinds ++ typats
@@ -1106,10 +1105,10 @@ consUseH98Syntax _ = True
conRepresentibleWithH98Syntax :: ConDecl Name -> Bool
conRepresentibleWithH98Syntax
(ConDecl {con_qvars = tvs, con_cxt = ctxt, con_res = ResTyH98 })
- = null tvs && null (unLoc ctxt)
+ = null (hsQTvBndrs tvs) && null (unLoc ctxt)
conRepresentibleWithH98Syntax
(ConDecl {con_qvars = tvs, con_cxt = ctxt, con_res = ResTyGADT (L _ t) })
- = null (unLoc ctxt) && f t (map (hsTyVarName . unLoc) tvs)
+ = null (unLoc ctxt) && f t (hsLTyVarNames tvs)
where -- Each type variable should be used exactly once in the
-- result type, and the result type must just be the type
-- constructor applied to type variables
diff --git a/compiler/typecheck/TcUnify.lhs b/compiler/typecheck/TcUnify.lhs
index 0b2429842d..c44ce31f2e 100644
--- a/compiler/typecheck/TcUnify.lhs
+++ b/compiler/typecheck/TcUnify.lhs
@@ -533,7 +533,9 @@ uType_defer items ty1 ty2
= ASSERT( not (null items) )
do { eqv <- newEq ty1 ty2
; loc <- getCtLoc (TypeEqOrigin (last items))
- ; emitFlat $ mkNonCanonical (Wanted loc eqv)
+ ; let ctev = Wanted { ctev_wloc = loc, ctev_evar = eqv
+ , ctev_pred = mkTcEqPred ty1 ty2 }
+ ; emitFlat $ mkNonCanonical ctev
-- Error trace only
-- NB. do *not* call mkErrInfo unless tracing is on, because
diff --git a/compiler/types/Coercion.lhs b/compiler/types/Coercion.lhs
index 1360baca6b..42e54ba47b 100644
--- a/compiler/types/Coercion.lhs
+++ b/compiler/types/Coercion.lhs
@@ -30,7 +30,7 @@ module Coercion (
-- ** Constructing coercions
mkReflCo, mkCoVarCo,
mkAxInstCo, mkAxInstRHS,
- mkPiCo, mkPiCos,
+ mkPiCo, mkPiCos, mkCoCast,
mkSymCo, mkTransCo, mkNthCo,
mkInstCo, mkAppCo, mkTyConAppCo, mkFunCo,
mkForAllCo, mkUnsafeCo,
@@ -672,6 +672,18 @@ mkPiCos vs co = foldr mkPiCo co vs
mkPiCo :: Var -> Coercion -> Coercion
mkPiCo v co | isTyVar v = mkForAllCo v co
| otherwise = mkFunCo (mkReflCo (varType v)) co
+
+mkCoCast :: Coercion -> Coercion -> Coercion
+-- (mkCoCast (c :: s1 ~# t1) (g :: (s1 ~# t1) ~# (s2 ~# t2)
+mkCoCast c g
+ = mkSymCo g1 `mkTransCo` c `mkTransCo` g2
+ where
+ -- g :: (s1 ~# s2) ~# (t1 ~# t2)
+ -- g1 :: s1 ~# t1
+ -- g2 :: s2 ~# t2
+ [_reflk, g1, g2] = decomposeCo 3 g
+ -- Remember, (~#) :: forall k. k -> k -> *
+ -- so it takes *three* arguments, not two
\end{code}
%************************************************************************
diff --git a/compiler/types/FunDeps.lhs b/compiler/types/FunDeps.lhs
index 8a158139cc..31ef9cc7ab 100644
--- a/compiler/types/FunDeps.lhs
+++ b/compiler/types/FunDeps.lhs
@@ -216,6 +216,10 @@ data Equation
data FDEq = FDEq { fd_pos :: Int -- We use '0' for the first position
, fd_ty_left :: Type
, fd_ty_right :: Type }
+
+instance Outputable FDEq where
+ ppr (FDEq { fd_pos = p, fd_ty_left = tyl, fd_ty_right = tyr })
+ = parens (int p <> comma <+> ppr tyl <> comma <+> ppr tyr)
\end{code}
Given a bunch of predicates that must hold, such as
diff --git a/compiler/types/TyCon.lhs b/compiler/types/TyCon.lhs
index d6a744c7ac..2c4931a3dd 100644
--- a/compiler/types/TyCon.lhs
+++ b/compiler/types/TyCon.lhs
@@ -22,7 +22,6 @@ module TyCon(
-- ** Constructing TyCons
mkAlgTyCon,
mkClassTyCon,
- mkIParamTyCon,
mkFunTyCon,
mkPrimTyCon,
mkKindTyCon,
@@ -859,11 +858,6 @@ mkClassTyCon :: Name -> Kind -> [TyVar] -> AlgTyConRhs -> Class -> RecFlag -> Ty
mkClassTyCon name kind tyvars rhs clas is_rec =
mkAlgTyCon name kind tyvars Nothing [] rhs (ClassTyCon clas) is_rec False
--- | Simpler specialization of 'mkAlgTyCon' for implicit paramaters
-mkIParamTyCon :: Name -> Kind -> TyVar -> AlgTyConRhs -> RecFlag -> TyCon
-mkIParamTyCon name kind tyvar rhs is_rec =
- mkAlgTyCon name kind [tyvar] Nothing [] rhs NoParentTyCon is_rec False
-
mkTupleTyCon :: Name
-> Kind -- ^ Kind of the resulting 'TyCon'
-> Arity -- ^ Arity of the tuple
diff --git a/compiler/types/Type.lhs b/compiler/types/Type.lhs
index e0de629da6..62cc7bbfd1 100644
--- a/compiler/types/Type.lhs
+++ b/compiler/types/Type.lhs
@@ -285,7 +285,7 @@ expandTypeSynonyms ty
= TyConApp tc (map go tys)
go (LitTy l) = LitTy l
go (TyVarTy tv) = TyVarTy tv
- go (AppTy t1 t2) = AppTy (go t1) (go t2)
+ go (AppTy t1 t2) = mkAppTy (go t1) (go t2)
go (FunTy t1 t2) = FunTy (go t1) (go t2)
go (ForAllTy tv t) = ForAllTy tv (go t)
\end{code}
@@ -973,14 +973,17 @@ getClassPredTys_maybe ty = case splitTyConApp_maybe ty of
_ -> Nothing
getEqPredTys :: PredType -> (Type, Type)
-getEqPredTys ty = case getEqPredTys_maybe ty of
- Just (ty1, ty2) -> (ty1, ty2)
- Nothing -> pprPanic "getEqPredTys" (ppr ty)
+getEqPredTys ty
+ = case splitTyConApp_maybe ty of
+ Just (tc, (_ : ty1 : ty2 : tys)) -> ASSERT( tc `hasKey` eqTyConKey && null tys )
+ (ty1, ty2)
+ _ -> pprPanic "getEqPredTys" (ppr ty)
getEqPredTys_maybe :: PredType -> Maybe (Type, Type)
-getEqPredTys_maybe ty = case splitTyConApp_maybe ty of
- Just (tc, [_, ty1, ty2]) | tc `hasKey` eqTyConKey -> Just (ty1, ty2)
- _ -> Nothing
+getEqPredTys_maybe ty
+ = case splitTyConApp_maybe ty of
+ Just (tc, [_, ty1, ty2]) | tc `hasKey` eqTyConKey -> Just (ty1, ty2)
+ _ -> Nothing
getIPPredTy_maybe :: PredType -> Maybe (IPName Name, Type)
getIPPredTy_maybe ty = case splitTyConApp_maybe ty of
diff --git a/compiler/types/Unify.lhs b/compiler/types/Unify.lhs
index 50a0fcf39a..de4f3fe865 100644
--- a/compiler/types/Unify.lhs
+++ b/compiler/types/Unify.lhs
@@ -516,36 +516,29 @@ uUnrefined subst tv1 ty2 (TyVarTy tv2)
= uUnrefined subst tv1 ty' ty'
| otherwise
- -- So both are unrefined; next, see if the kinds force the direction
- = case (k1_sub_k2, k2_sub_k1) of
- (True, True) -> choose subst
- (True, False) -> bindTv subst tv2 ty1
- (False, True) -> bindTv subst tv1 ty2
- (False, False) -> do
- { subst' <- unify subst k1 k2
- ; choose subst' }
- where subst_kind = mkTvSubst (mkInScopeSet (tyVarsOfTypes [k1,k2])) subst
- k1 = substTy subst_kind (tyVarKind tv1)
- k2 = substTy subst_kind (tyVarKind tv2)
- k1_sub_k2 = k1 `isSubKind` k2
- k2_sub_k1 = k2 `isSubKind` k1
- ty1 = TyVarTy tv1
- bind subst tv ty = return $ extendVarEnv subst tv ty
- choose subst = do
- { b1 <- tvBindFlag tv1
- ; b2 <- tvBindFlag tv2
- ; case (b1, b2) of
- (BindMe, _) -> bind subst tv1 ty2
- (Skolem, Skolem) -> failWith (misMatch ty1 ty2)
- (Skolem, _) -> bind subst tv2 ty1 }
+
+ = do { -- So both are unrefined; unify the kinds
+ ; subst' <- unify subst (tyVarKind tv1) (tyVarKind tv2)
+
+ -- And then bind one or the other,
+ -- depending on which is bindable
+ -- NB: unlike TcUnify we do not have an elaborate sub-kinding
+ -- story. That is relevant only during type inference, and
+ -- (I very much hope) is not relevant here.
+ ; b1 <- tvBindFlag tv1
+ ; b2 <- tvBindFlag tv2
+ ; let ty1 = TyVarTy tv1
+ ; case (b1, b2) of
+ (Skolem, Skolem) -> failWith (misMatch ty1 ty2)
+ (BindMe, _) -> return (extendVarEnv subst' tv1 ty2)
+ (_, BindMe) -> return (extendVarEnv subst' tv2 ty1) }
uUnrefined subst tv1 ty2 ty2' -- ty2 is not a type variable
| tv1 `elemVarSet` niSubstTvSet subst (tyVarsOfType ty2')
= failWith (occursCheck tv1 ty2) -- Occurs check
- | not (k2 `isSubKind` k1)
- = failWith (kindMisMatch tv1 ty2) -- Kind check
| otherwise
- = bindTv subst tv1 ty2 -- Bind tyvar to the synonym if poss
+ = do { subst' <- unify subst k1 k2
+ ; bindTv subst' tv1 ty2 } -- Bind tyvar to the synonym if poss
where
k1 = tyVarKind tv1
k2 = typeKind ty2'
@@ -626,13 +619,6 @@ lengthMisMatch tys1 tys2
= sep [ptext (sLit "Can't match unequal length lists"),
nest 2 (ppr tys1), nest 2 (ppr tys2) ]
-kindMisMatch :: TyVar -> Type -> SDoc
-kindMisMatch tv1 t2
- = vcat [ptext (sLit "Can't match kinds") <+> quotes (ppr (tyVarKind tv1)) <+>
- ptext (sLit "and") <+> quotes (ppr (typeKind t2)),
- ptext (sLit "when matching") <+> quotes (ppr tv1) <+>
- ptext (sLit "with") <+> quotes (ppr t2)]
-
occursCheck :: TyVar -> Type -> SDoc
occursCheck tv ty
= hang (ptext (sLit "Can't construct the infinite type"))
diff --git a/configure.ac b/configure.ac
index 8e3d9d2837..aeea6a4d9e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -161,6 +161,10 @@ if test "$BootingFromHc" = "NO"; then
or --with-ghc to specify a different GHC to use.])
fi
fi
+
+ GHC_PACKAGE_DB_FLAG=package-db
+ FP_COMPARE_VERSIONS([$GhcVersion],[-lt],[7.5],GHC_PACKAGE_DB_FLAG=package-conf)
+ AC_SUBST(GHC_PACKAGE_DB_FLAG)
fi;
# GHC is passed to Cabal, so we need a native path
diff --git a/docs/users_guide/flags.xml b/docs/users_guide/flags.xml
index 1d091d7e2f..b501961b4e 100644
--- a/docs/users_guide/flags.xml
+++ b/docs/users_guide/flags.xml
@@ -594,14 +594,38 @@
<entry>-</entry>
</row>
<row>
- <entry><option>-package-conf</option> <replaceable>file</replaceable></entry>
- <entry>Load more packages from <replaceable>file</replaceable></entry>
+ <entry><option>-package-db</option> <replaceable>file</replaceable></entry>
+ <entry>Add <replaceable>file</replaceable> to the package db stack.</entry>
<entry>static</entry>
<entry>-</entry>
</row>
<row>
- <entry><option>-no-user-package-conf</option></entry>
- <entry>Don't load the user's package config file.</entry>
+ <entry><option>-clear-package-db</option></entry>
+ <entry>Clear the package db stack.</entry>
+ <entry>static</entry>
+ <entry>-</entry>
+ </row>
+ <row>
+ <entry><option>-no-global-package-db</option></entry>
+ <entry>Remove the global package db from the stack.</entry>
+ <entry>static</entry>
+ <entry>-</entry>
+ </row>
+ <row>
+ <entry><option>-global-package-db</option></entry>
+ <entry>Add the global package db to the stack.</entry>
+ <entry>static</entry>
+ <entry>-</entry>
+ </row>
+ <row>
+ <entry><option>-no-user-package-db</option></entry>
+ <entry>Remove the user's package db from the stack.</entry>
+ <entry>static</entry>
+ <entry>-</entry>
+ </row>
+ <row>
+ <entry><option>-user-package-db</option></entry>
+ <entry>Add the user's package db to the stack.</entry>
<entry>static</entry>
<entry>-</entry>
</row>
diff --git a/docs/users_guide/packages.xml b/docs/users_guide/packages.xml
index 4a3e45f2fb..d1df2d4712 100644
--- a/docs/users_guide/packages.xml
+++ b/docs/users_guide/packages.xml
@@ -408,35 +408,89 @@ _ZCMain_main_closure
see GHC's package table by running GHC with the <option>-v</option>
flag.</para>
- <para>Package databases may overlap: for example, packages in the
- user database will override (<emphasis>shadow</emphasis>) those
- of the same name and version in the global database.</para>
+ <para>Package databases may overlap, and they are arranged in a stack
+ structure. Packages closer to the top of the stack will override
+ (<emphasis>shadow</emphasis>) those below them. By default, the stack
+ contains just the global and the user's package databases, in that
+ order.</para>
- <para>You can control the loading of package databases using the following
- GHC options:</para>
+ <para>You can control GHC's package database stack using the following
+ options:</para>
<variablelist>
<varlistentry>
<term>
- <option>-package-conf <replaceable>file</replaceable></option>
- <indexterm><primary><option>-package-conf</option></primary></indexterm>
+ <option>-package-db <replaceable>file</replaceable></option>
+ <indexterm><primary><option>-package-db</option></primary></indexterm>
</term>
<listitem>
- <para>Read in the package configuration file
- <replaceable>file</replaceable> in addition to the system
- default file and the user's local file. Packages in additional
- files read this way will override those in the global and user
- databases.</para>
+ <para>Add the package database <replaceable>file</replaceable> on top
+ of the current stack. Packages in additional databases read this
+ way will override those in the initial stack and those in
+ previously specified databases.</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>-no-user-package-conf</option>
- <indexterm><primary><option>-no-user-package-conf</option></primary>
+ <term><option>-no-global-package-db</option>
+ <indexterm><primary><option>-no-global-package-db</option></primary>
</indexterm>
</term>
<listitem>
- <para>Prevent loading of the user's local package database.</para>
+ <para>Remove the global package database from the package database
+ stack.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-no-user-package-db</option>
+ <indexterm><primary><option>-no-user-package-db</option></primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>Prevent loading of the user's local package database in the
+ initial stack.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-clear-package-db</option>
+ <indexterm><primary><option>-clear-package-db</option></primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>Reset the current package database stack. This option removes
+ every previously specified package database (including those
+ read from the <literal>GHC_PACKAGE_PATH</literal> environment
+ variable) from the package database stack.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-global-package-db</option>
+ <indexterm><primary><option>-global-package-db</option></primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>Add the global package database on top of the current stack.
+ This option can be used after
+ <literal>-no-global-package-db</literal> to specify the position in
+ the stack where the global package database should be
+ loaded.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-user-package-db</option>
+ <indexterm><primary><option>-user-package-db</option></primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>Add the user's package database on top of the current stack.
+ This option can be used after
+ <literal>-no-user-package-db</literal> to specify the position in
+ the stack where the user's package database should be
+ loaded.</para>
</listitem>
</varlistentry>
</variablelist>
@@ -456,11 +510,13 @@ _ZCMain_main_closure
packages.</para>
<para>If <literal>GHC_PACKAGE_PATH</literal> ends in a separator, then
- the default user and system package databases are appended, in that
- order. e.g. to augment the usual set of packages with a database of
- your own, you could say (on Unix):
-<screen>
-$ export GHC_PACKAGE_PATH=$HOME/.my-ghc-packages.conf:</screen>
+ the default package database stack (i.e. the user and global
+ package databases, in that order) is appended. For example, to augment
+ the usual set of packages with a database of your own, you could say
+ (on Unix):
+
+ <screen> $ export GHC_PACKAGE_PATH=$HOME/.my-ghc-packages.conf:</screen>
+
(use <literal>;</literal> instead of <literal>:</literal> on
Windows).</para>
@@ -601,12 +657,12 @@ haskell98-1.0.1.0
<literal>ghc-pkg</literal> knows about can be modified using the
<literal>GHC_PACKAGE_PATH</literal> environment variable (see <xref
linkend="ghc-package-path" />, and using
- <literal>--package-conf</literal> options on the
+ <literal>--package-db</literal> options on the
<literal>ghc-pkg</literal> command line.</para>
<para>When asked to modify a database, <literal>ghc-pkg</literal> modifies
the global database by default. Specifying <option>--user</option>
- causes it to act on the user database, or <option>--package-conf</option>
+ causes it to act on the user database, or <option>--package-db</option>
can be used to act on another database entirely. When multiple of these
options are given, the rightmost one is used as the database to act
upon.</para>
@@ -614,7 +670,7 @@ haskell98-1.0.1.0
<para>Commands that query the package database (list, latest,
describe, field, dot) operate on the list of databases specified by
the flags <option>--user</option>, <option>--global</option>, and
- <option>--package-conf</option>. If none of these flags are
+ <option>--package-db</option>. If none of these flags are
given, the default is <option>--global</option>
<option>--user</option>.</para>
@@ -888,8 +944,8 @@ ghc-pkg dot | tred | dot -Tpdf >pkgs.pdf
</indexterm>
</term>
<term>
- <option>-package-conf</option> <replaceable>file</replaceable>
- <indexterm><primary><option>-package-conf</option></primary>
+ <option>-package-db</option> <replaceable>file</replaceable>
+ <indexterm><primary><option>-package-db</option></primary>
</indexterm>
</term>
<listitem>
@@ -898,7 +954,7 @@ ghc-pkg dot | tred | dot -Tpdf >pkgs.pdf
also be the database modified by a <literal>register</literal>,
<literal>unregister</literal>, <literal>expose</literal> or
<literal>hide</literal> command, unless it is overridden by a later
- <option>--package-conf</option>, <option>--user</option> or
+ <option>--package-db</option>, <option>--user</option> or
<option>--global</option> option.</para>
</listitem>
</varlistentry>
diff --git a/docs/users_guide/runghc.xml b/docs/users_guide/runghc.xml
index 0681f00851..7d61f83ee1 100644
--- a/docs/users_guide/runghc.xml
+++ b/docs/users_guide/runghc.xml
@@ -32,7 +32,7 @@ runghc [runghc flags] [GHC flags] module [program args]
with a dash then you need to prefix it with
<literal>--ghc-arg=</literal> or runghc will think that it is the
program to run, e.g.
- <literal>runghc -package-conf --ghc-arg=foo.conf Main.hs</literal>.
+ <literal>runghc -package-db --ghc-arg=foo.conf Main.hs</literal>.
</para>
</sect1>
diff --git a/ghc.mk b/ghc.mk
index 195310bef6..a23171caa7 100644
--- a/ghc.mk
+++ b/ghc.mk
@@ -899,7 +899,7 @@ install_packages: rts/package.conf.install
$(call INSTALL_DIR,"$(DESTDIR)$(topdir)")
$(call removeTrees,"$(INSTALLED_PACKAGE_CONF)")
$(call INSTALL_DIR,"$(INSTALLED_PACKAGE_CONF)")
- "$(INSTALLED_GHC_PKG_REAL)" --force --global-conf "$(INSTALLED_PACKAGE_CONF)" update rts/package.conf.install
+ "$(INSTALLED_GHC_PKG_REAL)" --force --global-package-db "$(INSTALLED_PACKAGE_CONF)" update rts/package.conf.install
$(foreach p, $(INSTALLED_PKG_DIRS), \
$(call make-command, \
CROSS_COMPILE="$(CrossCompilePrefix)" \
diff --git a/ghc/InteractiveUI.hs b/ghc/InteractiveUI.hs
index 1a80b49639..efafd25d23 100644
--- a/ghc/InteractiveUI.hs
+++ b/ghc/InteractiveUI.hs
@@ -993,7 +993,7 @@ pprInfo pefas (thing, fixity, insts)
where
show_fixity fix
| fix == GHC.defaultFixity = empty
- | otherwise = ppr fix <+> ppr (GHC.getName thing)
+ | otherwise = ppr fix <+> pprInfixName (GHC.getName thing)
-----------------------------------------------------------------------------
-- :main
diff --git a/libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs b/libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs
index 242b7c02d1..7a254b7ac6 100644
--- a/libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs
+++ b/libraries/bin-package-db/Distribution/InstalledPackageInfo/Binary.hs
@@ -136,7 +136,8 @@ instance Binary License where
put PublicDomain = do putWord8 5
put AllRightsReserved = do putWord8 6
put OtherLicense = do putWord8 7
- put (UnknownLicense str) = do putWord8 8; put str
+ put (Apache v) = do putWord8 8; put v
+ put (UnknownLicense str) = do putWord8 9; put str
get = do
n <- getWord8
@@ -149,6 +150,7 @@ instance Binary License where
5 -> return PublicDomain
6 -> return AllRightsReserved
7 -> return OtherLicense
+ 8 -> do v <- get; return (Apache v)
_ -> do str <- get; return (UnknownLicense str)
instance Binary Version where
diff --git a/mk/config.mk.in b/mk/config.mk.in
index b998946239..1cf8685383 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -543,6 +543,8 @@ compiler/cmm/Bitmap_HC_OPTS += -ffull-laziness
# for some unknown reason, so turn full-laziness back on for this module.
endif
+GHC_PACKAGE_DB_FLAG = @GHC_PACKAGE_DB_FLAG@
+
#-----------------------------------------------------------------------------
# C compiler
#
diff --git a/rules/distdir-way-opts.mk b/rules/distdir-way-opts.mk
index dcbd9cb8a6..bbd37d1ee1 100644
--- a/rules/distdir-way-opts.mk
+++ b/rules/distdir-way-opts.mk
@@ -61,7 +61,7 @@ define distdir-way-opts # args: $1 = dir, $2 = distdir, $3 = way, $4 = stage
#
# $1_$2_EXTRA_HC_OPTS GHC options for this dir/distdir mk/build.mk
#
-# $1_$2_HC_PKGCONF -package-conf flag if necessary rules/package-config.mk
+# $1_$2_HC_PKGCONF -package-db flag if necessary rules/package-config.mk
#
# $1_$2_HS_SRC_DIRS dirs relative to $1 containing $1/$2/package-data.mk
# source files
diff --git a/rules/package-config.mk b/rules/package-config.mk
index e0c9757862..1173e5f025 100644
--- a/rules/package-config.mk
+++ b/rules/package-config.mk
@@ -34,10 +34,10 @@ $1_$2_HC_MK_DEPEND = $$($1_$2_HC)
# on cygwin we get a dep on c:/ghc/..., and make gets confused by the :
$1_$2_HC_MK_DEPEND_DEP =
$1_$2_HC_DEP =
-$1_$2_HC_PKGCONF = -package-conf $$(BOOTSTRAPPING_CONF)
-$1_$2_GHC_PKG_OPTS = --package-conf=$$(BOOTSTRAPPING_CONF)
+$1_$2_HC_PKGCONF = -$(GHC_PACKAGE_DB_FLAG) $$(BOOTSTRAPPING_CONF)
+$1_$2_GHC_PKG_OPTS = --$(GHC_PACKAGE_DB_FLAG)=$$(BOOTSTRAPPING_CONF)
$1_$2_CONFIGURE_OPTS += --package-db=$$(TOP)/$$(BOOTSTRAPPING_CONF)
-$1_$2_MORE_HC_OPTS += -no-user-package-conf
+$1_$2_MORE_HC_OPTS += -no-user-$(GHC_PACKAGE_DB_FLAG)
$1_$2_MORE_HC_OPTS += -rtsopts
else
$1_$2_HC_PKGCONF =
@@ -51,7 +51,7 @@ $1_$2_GHC_PKG_OPTS =
$1_$2_HC_MK_DEPEND = $$(GHC_STAGE1)
$1_$2_HC_MK_DEPEND_DEP = $$($1_$2_HC_MK_DEPEND)
$1_$2_HC_DEP = $$($1_$2_HC)
-$1_$2_MORE_HC_OPTS += -no-user-package-conf
+$1_$2_MORE_HC_OPTS += -no-user-package-db
$1_$2_MORE_HC_OPTS += -rtsopts
endif
diff --git a/utils/ghc-cabal/Main.hs b/utils/ghc-cabal/Main.hs
index c24f127422..0f11eea497 100644
--- a/utils/ghc-cabal/Main.hs
+++ b/utils/ghc-cabal/Main.hs
@@ -190,7 +190,7 @@ doInstall ghc ghcpkg strip topdir directory distDir
programPostConf = \_ _ -> return ["-B" ++ topdir],
programFindLocation = \_ -> return (Just ghc) }
ghcPkgProgram' = ghcPkgProgram {
- programPostConf = \_ _ -> return $ ["--global-conf", ghcpkgconf]
+ programPostConf = \_ _ -> return $ ["--global-package-db", ghcpkgconf]
++ ["--force" | not (null myDestDir) ],
programFindLocation = \_ -> return (Just ghcpkg) }
stripProgram' = stripProgram {
diff --git a/utils/ghc-cabal/ghc.mk b/utils/ghc-cabal/ghc.mk
index 3ee2b13fa5..0a3e920e7a 100644
--- a/utils/ghc-cabal/ghc.mk
+++ b/utils/ghc-cabal/ghc.mk
@@ -27,7 +27,7 @@ $(GHC_CABAL_DIR)/dist/build/tmp/ghc-cabal$(exeext): $(wildcard libraries/Cabal/C
$(GHC_CABAL_DIR)/dist/build/tmp/ghc-cabal$(exeext): $(GHC_CABAL_DIR)/Main.hs $(TOUCH_DEP) | $$(dir $$@)/. bootstrapping/.
"$(GHC)" $(SRC_HC_OPTS) --make $(GHC_CABAL_DIR)/Main.hs -o $@ \
- -no-user-package-conf \
+ -no-user-$(GHC_PACKAGE_DB_FLAG) \
-Wall \
-DCABAL_VERSION=$(CABAL_VERSION) \
-odir bootstrapping \
diff --git a/utils/ghc-pkg/Main.hs b/utils/ghc-pkg/Main.hs
index e29301d933..e63139e997 100644
--- a/utils/ghc-pkg/Main.hs
+++ b/utils/ghc-pkg/Main.hs
@@ -119,11 +119,11 @@ flags = [
"use the current user's package database",
Option [] ["global"] (NoArg FlagGlobal)
"use the global package database",
- Option ['f'] ["package-conf"] (ReqArg FlagConfig "FILE")
+ Option ['f'] ["package-db"] (ReqArg FlagConfig "FILE")
"use the specified package config file",
- Option [] ["global-conf"] (ReqArg FlagGlobalConfig "FILE")
+ Option [] ["global-package-db"] (ReqArg FlagGlobalConfig "FILE")
"location of the global package config",
- Option [] ["no-user-package-conf"] (NoArg FlagNoUserDb)
+ Option [] ["no-user-package-db"] (NoArg FlagNoUserDb)
"never read the user package database",
Option [] ["force"] (NoArg FlagForce)
"ignore missing dependencies, directories, and libraries",
@@ -177,8 +177,8 @@ usageHeader prog = substProg prog $
" $p init {path}\n" ++
" Create and initialise a package database at the location {path}.\n" ++
" Packages can be registered in the new database using the register\n" ++
- " command with --package-conf={path}. To use the new database with GHC,\n" ++
- " use GHC's -package-conf flag.\n" ++
+ " command with --package-db={path}. To use the new database with GHC,\n" ++
+ " use GHC's -package-db flag.\n" ++
"\n" ++
" $p register {filename | -}\n" ++
" Register the package using the specified installed package\n" ++
@@ -247,7 +247,7 @@ usageHeader prog = substProg prog $
" Regenerate the package database cache. This command should only be\n" ++
" necessary if you added a package to the database by dropping a file\n" ++
" into the database directory manually. By default, the global DB\n" ++
- " is recached; to recache a different DB use --user or --package-conf\n" ++
+ " is recached; to recache a different DB use --user or --package-db\n" ++
" as appropriate.\n" ++
"\n" ++
" Substring matching is supported for {module} in find-module and\n" ++
@@ -257,13 +257,13 @@ usageHeader prog = substProg prog $
" When asked to modify a database (register, unregister, update,\n"++
" hide, expose, and also check), ghc-pkg modifies the global database by\n"++
" default. Specifying --user causes it to act on the user database,\n"++
- " or --package-conf can be used to act on another database\n"++
+ " or --package-db can be used to act on another database\n"++
" entirely. When multiple of these options are given, the rightmost\n"++
" one is used as the database to act upon.\n"++
"\n"++
" Commands that query the package database (list, tree, latest, describe,\n"++
" field) operate on the list of databases specified by the flags\n"++
- " --user, --global, and --package-conf. If none of these flags are\n"++
+ " --user, --global, and --package-db. If none of these flags are\n"++
" given, the default is --global --user.\n"++
"\n" ++
" The following optional flags are also accepted:\n"
@@ -471,9 +471,9 @@ getPkgDatabases :: Verbosity
getPkgDatabases verbosity modify use_cache expand_vars my_flags = do
-- first we determine the location of the global package config. On Windows,
-- this is found relative to the ghc-pkg.exe binary, whereas on Unix the
- -- location is passed to the binary using the --global-config flag by the
+ -- location is passed to the binary using the --global-package-db flag by the
-- wrapper script.
- let err_msg = "missing --global-conf option, location of global package.conf unknown\n"
+ let err_msg = "missing --global-package-db option, location of global package database unknown\n"
global_conf <-
case [ f | FlagGlobalConfig f <- my_flags ] of
[] -> do mb_dir <- getLibDir
diff --git a/utils/ghc-pkg/ghc-pkg.wrapper b/utils/ghc-pkg/ghc-pkg.wrapper
index fad4bdfca0..3a14de1e22 100644
--- a/utils/ghc-pkg/ghc-pkg.wrapper
+++ b/utils/ghc-pkg/ghc-pkg.wrapper
@@ -1,5 +1,5 @@
#!/bin/sh
PKGCONF="$topdir/package.conf.d"
-exec "$executablename" --global-conf "$PKGCONF" ${1+"$@"}
+exec "$executablename" --global-package-db "$PKGCONF" ${1+"$@"}
diff --git a/utils/ghc-pkg/ghc.mk b/utils/ghc-pkg/ghc.mk
index 4f4967e07f..8ec3fd0097 100644
--- a/utils/ghc-pkg/ghc.mk
+++ b/utils/ghc-pkg/ghc.mk
@@ -24,7 +24,7 @@ else
$(call removeFiles,$@)
echo "#!/bin/sh" >>$@
echo "PKGCONF=$(TOP)/$(INPLACE_PACKAGE_CONF)" >>$@
- echo '$(TOP)/$< --global-conf $$PKGCONF $${1+"$$@"}' >> $@
+ echo '$(TOP)/$< --global-package-db $$PKGCONF $${1+"$$@"}' >> $@
chmod +x $@
endif
@@ -38,7 +38,7 @@ else
$(call removeFiles,$@)
echo "#!/bin/sh" >>$@
echo "PKGCONF=$(TOP)/$(INPLACE_PACKAGE_CONF)" >>$@
- echo '$(TOP)/$< --global-conf $$PKGCONF $${1+"$$@"}' >> $@
+ echo '$(TOP)/$< --global-package-db $$PKGCONF $${1+"$$@"}' >> $@
chmod +x $@
endif
@@ -53,7 +53,7 @@ endif
#
utils/ghc-pkg/dist/build/tmp/$(utils/ghc-pkg_dist_PROG)$(exeext): utils/ghc-pkg/Main.hs utils/ghc-pkg/Version.hs | bootstrapping/. $$(dir $$@)/. $(GHC_CABAL_INPLACE)
"$(GHC)" $(SRC_HC_OPTS) --make utils/ghc-pkg/Main.hs -o $@ \
- -no-user-package-conf \
+ -no-user-$(GHC_PACKAGE_DB_FLAG) \
-Wall -fno-warn-unused-imports -fno-warn-warnings-deprecations \
$(SRC_HC_WARNING_OPTS) \
-DCABAL_VERSION=$(CABAL_VERSION) \