
#14629: Seemingly unused qualified import affects method visibility -------------------------------------+------------------------------------- Reporter: gelisam | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.2.2 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Poor/confusing Unknown/Multiple | error message Test Case: | Blocked By: Blocking: | Related Tickets: ticket:3992, | ticket:10890 Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Here is a simple test case: {{{#!hs module MyLib where class MyClass a where myMethod :: a -> a }}} {{{#!hs module MyModule where import MyLib (MyClass) --import qualified MyLib as L data Foo = Foo instance MyClass Foo where -- error: ‘myMethod’ is not a (visible) method of class ‘MyClass’ myMethod Foo = Foo }}} Since I have only imported `MyClass` and not its methods (that would be `import MyLib (MyClass(..))`), the error is correct, `myMethod` is not visible. But if I uncomment the `import qualified MyLib as L` line, the error disappears even though I do not use `L` anywhere. Writing `L.myMethod Foo = Foo` is not even legal! ----- I filed this under "confusing error message", so let me show you the conditions under which the above behaviour was confusing. We were using [https://hackage.haskell.org/package/classy- prelude-1.3.1/docs/ClassyPrelude.html classy-prelude] instead of `Prelude`, but we were not familiar with all the differences between the two preludes. We started with code like this, which did not compile: {{{#!hs {-# LANGUAGE NoImplicitPrelude #-} module MyModule import ClassyPrelude data Foo a = Foo instance Foldable Foo where -- 'foldMap' is not a (visible) method of class 'Foldable' foldMap = undefined }}} So we clarified that we meant `Prelude.Foldable`, in case `ClassyFoldable.Foldable` meant something different. {{{#!hs {-# LANGUAGE NoImplicitPrelude #-} module MyModule import ClassyPrelude import qualified Prelude data Foo a = Foo instance Prelude.Foldable Foo where foldMap = undefined }}} This compiled, so we first thought that `Prelude.Foldable` and `ClassyPrelude.Foldable` were two different type classes, but we later discovered that `ClassyPrelude.Foldable` is a re-export of `Prelude.Foldable`. So the following means the same thing and also compiles: {{{#!hs {-# LANGUAGE NoImplicitPrelude #-} module MyModule import ClassyPrelude import qualified Prelude data Foo a = Foo instance ClassyPrelude.Foldable Foo where foldMap = undefined }}} At this point, the qualified `Prelude` import doesn't seem used anywhere, so we thought it was safe to remove it: {{{#!hs {-# LANGUAGE NoImplicitPrelude #-} import ClassyPrelude data Foo a = Foo instance ClassyPrelude.Foldable Foo where -- 'foldMap' is not a (visible) method of class 'Foldable' foldMap = undefined }}} But `ClassyPrelude.foldMap` is ''not'' the same as `Prelude.foldMap`, so this did not compile and it wasn't clear why. One way to make this less confusing would be to allow qualified method names; this way, we would have tried both `Prelude.foldMap = undefined` and `ClassyPrelude.foldMap = undefined`, and we would have discovered the source of the problem. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14629 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler