
#13251: Must perform family consistency check on non-imported identifiers -------------------------------------+------------------------------------- Reporter: ezyang | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.1 checker) | Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: Type of failure: GHC accepts | Unknown/Multiple invalid program | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by rwbarton: @@ -53,1 +53,2 @@ - up with identifiers without imports include overloading, see #13102. + up with identifiers without imports include overloading, see + ticket:13102#comment:13. New description: Currently, the family consistency check checks pairs of *imported* modules (and the modules they transitively import) for consistency. However, there are a number of mechanisms by which we can refer to an identifier from a module without explicitly importing it. Here is one example from Template Haskell: {{{ -- A.hs {-# LANGUAGE TypeFamilies #-} module A where type family F a -- B.hs {-# LANGUAGE TypeFamilies #-} module B where import A type instance F Bool = String g :: F Bool g = "af" -- C.hs {-# LANGUAGE TypeFamilies #-} module C where import A type instance F Bool = Int h :: F Bool -> IO () h = print -- D.hs {-# LANGUAGE TemplateHaskell #-} import C import Language.Haskell.TH.Syntax main = h $( return (VarE (Name (OccName "g") (NameG VarName (PkgName "main") (ModName "B")))) ) }}} This does an unsafe coerce: {{{ ezyang@sabre:~/Dev/labs/T13102$ ghc-head --make B.hs D.hs -fforce-recomp [1 of 4] Compiling A ( A.hs, A.o ) [2 of 4] Compiling B ( B.hs, B.o ) [3 of 4] Compiling C ( C.hs, C.o ) [4 of 4] Compiling Main ( D.hs, D.o ) Linking D ... ezyang@sabre:~/Dev/labs/T13102$ ./D 8070450533355229282 }}} Clearly, checking consistency on imports is not enough: we must also check up on original names that come by other mechanisms. (Other ways we can end up with identifiers without imports include overloading, see ticket:13102#comment:13. A few things to note about how to fix this: * Currently, type family instances are checked for consistency as we process imports. Template Haskell splices can occur much later in a Haskell file, so we must correspondingly do these checks later. * If we refer to an identifier by synthesizing a name manually, it is as if we imported it. This also means that a reference of this sort implies an implicit import of the defining module (#13102) and we should consider instances from it visible (at the moment, it's not considered visible.) (Actually, with TH, this is a bit tricky, because if we take these semantics, an instance might be visible below a top-level splice, but invisible above it.) * It is probably simplest if the type family compatibility check happens at the end. So we should go ahead and revive idea (2) from https://ghc.haskell.org/trac/ghc/ticket/11062#comment:9 ; if there are overlapping families we should just not reduce the type family. * For wired in things, it's pretty easy to find out if we have an implicit import: if we bang on `checkWiredInTyCon`, that means we intended for the instance to visible; so we should collect all of the TyCons we banged on this way. For TH, this isn't exactly going to work, but maybe we can just track when NameGs get synthesized. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13251#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler