[commit: ghc] imp-param-class: Restore custom handling of IP for ambiguity (due to a fun-dep bug in GHC). (28dbc38)

Iavor Diatchki diatchki at galois.com
Mon May 28 05:42:06 CEST 2012


Repository : ssh://darcs.haskell.org//srv/darcs/ghc

On branch  : imp-param-class

http://hackage.haskell.org/trac/ghc/changeset/28dbc389100e7bcbf4360ce2d192e534b73652ab

>---------------------------------------------------------------

commit 28dbc389100e7bcbf4360ce2d192e534b73652ab
Author: Iavor S. Diatchki <iavor.diatchki at gmail.com>
Date:   Sun May 27 19:56:03 2012 -0700

    Restore custom handling of IP for ambiguity (due to a fun-dep bug in GHC).
    
    GHC considers types like these to be ambiguous:
    
    f :: IP "c" a => String
    
    This is not quite right, and the explanation of why that happens
    (from module FunDeps) also seems to be not quite correct: all variables
    appearing in a type and not showing up in the environment should
    be generalized, even though they might be fully determined from nothing
    (as above, for example).
    
    Until we fix that problem, however, we keep the special rules for
    ambiguity and implicit parameters.

>---------------------------------------------------------------

 compiler/typecheck/TcMType.lhs |   29 ++++++++++++++++++++++++++---
 1 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/compiler/typecheck/TcMType.lhs b/compiler/typecheck/TcMType.lhs
index d05b1dd..e0529a8 100644
--- a/compiler/typecheck/TcMType.lhs
+++ b/compiler/typecheck/TcMType.lhs
@@ -1342,7 +1342,7 @@ checkAmbiguity forall_tyvars theta tau_tyvars
     extended_tau_vars = growThetaTyVars theta tau_tyvars
 
 	-- See Note [Implicit parameters and ambiguity] in TcSimplify
-    is_ambig pred     = isClassPred  pred &&
+    is_ambig pred     = not (isIPPred pred) && isClassPred  pred &&
 			any ambig_var (varSetElems (tyVarsOfType pred))
 
     ambig_var ct_var  = (ct_var `elem` forall_tyvars) &&
@@ -1377,17 +1377,40 @@ growPredTyVars :: TcPredType
                -> TyVarSet	-- The set to extend
 	       -> TyVarSet	-- TyVars of the predicate if it intersects
 	       	  		-- the set, or is implicit parameter
-growPredTyVars pred tvs = go (classifyPredType pred)
+growPredTyVars pred tvs = goClass pred
   where
     grow pred_tvs | pred_tvs `intersectsVarSet` tvs = pred_tvs
                   | otherwise                       = emptyVarSet
+    -- See Note [Implicit parameter and ambiguity]
+    goClass p | isIPPred p = tyVarsOfType p
+    goClass p              = go (classifyPredType p)
 
     go (ClassPred _ tys) = grow (tyVarsOfTypes tys)
     go (EqPred ty1 ty2)  = grow (tyVarsOfType ty1 `unionVarSet` tyVarsOfType ty2)
-    go (TuplePred ts)    = unionVarSets (map (go . classifyPredType) ts)
+    go (TuplePred ts)    = unionVarSets (map goClass ts)
     go (IrredPred ty)    = grow (tyVarsOfType ty)
 \end{code}
 
+Note [Implicit parameters and ambiguity].
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Only a *class* predicate can give rise to ambiguity
+An *implicit parameter* cannot.  For example:
+        foo :: (?x :: [a]) => Int
+        foo = length ?x
+is fine.  The call site will suppply a particular 'x'
+
+Furthermore, the type variables fixed by an implicit parameter
+propagate to the others.  E.g.
+        foo :: (Show a, ?x::[a]) => Int
+        foo = show (?x++?x)
+The type of foo looks ambiguous.  But it isn't, because at a call site
+we might have
+        let ?x = 5::Int in foo
+and all is well.  In effect, implicit parameters are, well, parameters,
+so we can take their type variables into account as part of the
+"tau-tvs" stuff.  This is done in the function 'FunDeps.grow'.
+
+
 \begin{code}
 checkThetaCtxt :: UserTypeCtxt -> ThetaType -> SDoc
 checkThetaCtxt ctxt theta





More information about the Cvs-ghc mailing list