From 97db0edc4e637dd61ec635d1f9b6b6dd25ad890c Mon Sep 17 00:00:00 2001 From: Simon Peyton Jones Date: Tue, 8 Jan 2013 08:26:40 +0000 Subject: Re-engineer the ambiguity test for user type signatures Two main changes. First, re-engineer the ambiguity test. Previously TcMType.checkAmbiguity used a rather syntactic test to detect some types that are certainly ambiguous. But a much easier test is available, and it is used for inferred types in TcBinds. Namely is ambiguous iff `TcUnify.isSubType` fails to hold, where "isSubType" means "is provably more polymorphic than". Example: C a => Int is ambiguous, because isSubType instantiates the (C a => Int) to (C alpha => Int) and then tries to deduce (C alpha) from (C a). This is Martin Sulzmann's definition of ambiguity. (Defn 10 of "Understanding functional dependencies via constraint handling rules", JFP.) This change is neat, reduces code, and correctly rejects more programs. However is *is* just possible to have a useful program that would be rejected. For example class C a b f :: C Int b => Int -> Int Here 'f' would be rejected as having an ambiguous type. But it is just possible that, at a *call* site there might be an instance declaration instance C Int b, which does not constrain 'b' at all. This is pretty strange -- why is 'b' overloaded at all? -- but it's possible, so I also added a flag -XAllowAmbiguousTypes that simply removes the ambiguity check. Let's see if anyone cares. Meanwhile the earlier error report will be useful for everyone else. A handful of regression tests had to be adjusted as a result, because they used ambiguous types, somewhat accidentally. Second, split TcMType (already too large) into two * TcMType: a low-level module dealing with monadic operations like zonking, creating new evidence variables, etc * TcValidity: a brand-new higher-level module dealing with validity checking for types: checkValidType, checkValidInstance, checkFamInstPats etc Apart from the fact that TcMType was too big, this allows TcValidity to import TcUnify(tcSubType) without causing a loop. --- compiler/ghc.cabal.in | 1 + 1 file changed, 1 insertion(+) (limited to 'compiler/ghc.cabal.in') diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in index 44d0952b33..47225b5164 100644 --- a/compiler/ghc.cabal.in +++ b/compiler/ghc.cabal.in @@ -362,6 +362,7 @@ Library TcHsType TcInstDcls TcMType + TcValidity TcMatches TcPat TcRnDriver -- cgit v1.2.1