[commit: ghc] master: Refine 'type_determines_value' in Specialise. Fix Trac #7785. (5949ff2)
Simon Peyton Jones
simonpj at microsoft.com
Thu May 30 15:06:30 CEST 2013
Repository : http://darcs.haskell.org/ghc.git/
On branch : master
https://github.com/ghc/ghc/commit/5949ff2ddb715c3218c2cb96fd7170bae2ee02db
>---------------------------------------------------------------
commit 5949ff2ddb715c3218c2cb96fd7170bae2ee02db
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date: Thu May 30 12:22:38 2013 +0100
Refine 'type_determines_value' in Specialise. Fix Trac #7785.
See Note [Type determines value] in Specialise.
>---------------------------------------------------------------
compiler/specialise/Specialise.lhs | 40 ++++++++++++++++++++++++++++++--------
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/compiler/specialise/Specialise.lhs b/compiler/specialise/Specialise.lhs
index 212a7fe..a161444 100644
--- a/compiler/specialise/Specialise.lhs
+++ b/compiler/specialise/Specialise.lhs
@@ -10,7 +10,7 @@ module Specialise ( specProgram ) where
import Id
import TcType hiding( substTy, extendTvSubstList )
-import Type( TyVar, isDictTy, mkPiTypes )
+import Type( TyVar, isDictTy, mkPiTypes, classifyPredType, PredTree(..), isIPClass )
import Coercion( Coercion )
import CoreMonad
import qualified CoreSubst
@@ -1597,7 +1597,9 @@ mkCallUDs :: SpecEnv -> Id -> [CoreExpr] -> UsageDetails
mkCallUDs env f args
| not (want_calls_for f) -- Imported from elsewhere
|| null theta -- Not overloaded
- || not (all type_determines_value theta)
+ = emptyUDs
+
+ | not (all type_determines_value theta)
|| not (spec_tys `lengthIs` n_tyvars)
|| not ( dicts `lengthIs` n_dicts)
|| not (any (interestingDict env) dicts) -- Note [Interesting dictionary arguments]
@@ -1625,14 +1627,36 @@ mkCallUDs env f args
want_calls_for f = isLocalId f || isInlinablePragma (idInlinePragma f)
- type_determines_value pred = isClassPred pred && not (isIPPred pred)
- -- Only specialise if all overloading is on non-IP *class* params,
- -- because these are the ones whose *type* determines their *value*.
- -- In ptic, with implicit params, the type args
- -- *don't* say what the value of the implicit param is!
- -- See Trac #7101
+ type_determines_value pred -- See Note [Type determines value]
+ = case classifyPredType pred of
+ ClassPred cls _ -> not (isIPClass cls)
+ TuplePred ps -> all type_determines_value ps
+ EqPred {} -> True
+ IrredPred {} -> True -- Things like (D []) where D is a
+ -- Constraint-ranged family; Trac #7785
\end{code}
+Note [Type determines value]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Only specialise if all overloading is on non-IP *class* params,
+because these are the ones whose *type* determines their *value*. In
+parrticular, with implicit params, the type args *don't* say what the
+value of the implicit param is! See Trac #7101
+
+However, consider
+ type family D (v::*->*) :: Constraint
+ type instance D [] = ()
+ f :: D v => v Char -> Int
+If we see a call (f "foo"), we'll pass a "dictionary"
+ () |> (g :: () ~ D [])
+and it's good to specialise f at this dictionary.
+
+So the question is: can an implicit parameter "hide inside" a
+type-family constraint like (D a). Well, no. We don't allow
+ type instance D Maybe = ?x:Int
+Hence the IrredPred case in type_determines_value.
+See Trac #7785.
+
Note [Interesting dictionary arguments]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider this
More information about the ghc-commits
mailing list