summaryrefslogtreecommitdiff
path: root/compiler/specialise
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2016-06-20 15:48:09 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2016-06-21 14:52:56 +0100
commitd09e982c534b20908064f36d701a1a3a6a2eb55a (patch)
tree5e4903b63b77bbf2547be0b8d96ab50fda9616ce /compiler/specialise
parent7301404dfd317684418890799a587c7c684ddb63 (diff)
downloadhaskell-d09e982c534b20908064f36d701a1a3a6a2eb55a.tar.gz
Don't quantify over Refl in a RULE
This fixes Trac #12212. It's quite hard to provoke, but I've added a standalone test case that does so. The issue is explained in Note [Evidence foralls] in Specialise.
Diffstat (limited to 'compiler/specialise')
-rw-r--r--compiler/specialise/Specialise.hs35
1 files changed, 29 insertions, 6 deletions
diff --git a/compiler/specialise/Specialise.hs b/compiler/specialise/Specialise.hs
index d587eebab9..abd15c8564 100644
--- a/compiler/specialise/Specialise.hs
+++ b/compiler/specialise/Specialise.hs
@@ -12,8 +12,8 @@ module Specialise ( specProgram, specUnfolding ) where
import Id
import TcType hiding( substTy )
import Type hiding( substTy, extendTvSubstList )
-import Coercion( Coercion )
import Module( Module, HasModule(..) )
+import Coercion( Coercion )
import CoreMonad
import qualified CoreSubst
import CoreUnfold
@@ -22,7 +22,7 @@ import VarEnv
import CoreSyn
import Rules
import CoreUtils ( exprIsTrivial, applyTypeToArgs, mkCast )
-import CoreFVs ( exprFreeVars, exprsFreeVars, idFreeVars )
+import CoreFVs ( exprFreeVars, exprsFreeVars, idFreeVars, exprsFreeIdsList )
import UniqSupply
import Name
import MkId ( voidArgId, voidPrimId )
@@ -1227,6 +1227,9 @@ specCalls mb_mod env rules_for_me calls_for_me fn rhs
-- Construct the new binding
-- f1 = SUBST[a->t1,c->t3, d1->d1', d2->d2'] (/\ b -> rhs)
+ -- PLUS the rule
+ -- RULE "SPEC f" forall b d1' d2'. f b d1' d2' = f1 b
+ -- In the rule, d1' and d2' are just wildcards, not used in the RHS
-- PLUS the usage-details
-- { d1' = dx1; d2' = dx2 }
-- where d1', d2' are cloned versions of d1,d2, with the type substitution
@@ -1249,9 +1252,10 @@ specCalls mb_mod env rules_for_me calls_for_me fn rhs
; let (rhs_env2, dx_binds, spec_dict_args)
= bindAuxiliaryDicts rhs_env rhs_dict_ids call_ds inst_dict_ids
ty_args = mk_ty_args call_ts poly_tyvars
- rule_args = ty_args ++ map varToCoreExpr inst_dict_ids
- -- varToCoreExpr does the right thing for CoVars
- rule_bndrs = poly_tyvars ++ inst_dict_ids
+ ev_args = map varToCoreExpr inst_dict_ids -- ev_args, ev_bndrs:
+ ev_bndrs = exprsFreeIdsList ev_args -- See Note [Evidence foralls]
+ rule_args = ty_args ++ ev_args
+ rule_bndrs = poly_tyvars ++ ev_bndrs
; dflags <- getDynFlags
; if already_covered dflags rule_args then
@@ -1335,7 +1339,26 @@ specCalls mb_mod env rules_for_me calls_for_me fn rhs
; return (Just ((spec_f_w_arity, spec_rhs), final_uds, spec_env_rule)) } }
-{-
+{- Note [Evidence foralls]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+Suppose (Trac #12212) that we are specialising
+ f :: forall a b. (Num a, F a ~ F b) => blah
+with a=b=Int. Then the RULE will be something like
+ RULE forall (d:Num Int) (g :: F Int ~ F Int).
+ f Int Int d g = f_spec
+But both varToCoreExpr (when constructing the LHS args), and the
+simplifier (when simplifying the LHS args), will transform to
+ RULE forall (d:Num Int) (g :: F Int ~ F Int).
+ f Int Int d <F Int> = f_spec
+by replacing g with Refl. So now 'g' is unbound, which results in a later
+crash. So we use Refl right off the bat, and do not forall-quantify 'g':
+ * varToCoreExpr generates a Refl
+ * exprsFreeIdsList returns the Ids bound by the args,
+ which won't include g
+
+You might wonder if this will match as often, but the simplifer replaces
+complicated Refl coercions with Refl pretty aggressively.
+
Note [Orphans and auto-generated rules]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When we specialise an INLINEABLE function, or when we have