[GHC] #14629: Seemingly unused qualified import affects method visibility

#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

#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 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Poor/confusing | Unknown/Multiple error message | Test Case: Blocked By: | Blocking: Related Tickets: ticket:3992, | Differential Rev(s): ticket:10890 | Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): The logic is this: * If you export (or re-export) a class without one or more of its methods, you are trying to hide the very existence of that method in the class, so no client should be able to give an implementation for it. * But if you export it (even if only qualified) you are exposing it, so an instance can use it. * It would obviously be very tiresome to say that a method must be in scope ''unqualified'' in order to use it in an instance declaration. So the test is "is the method in scope, qualified or unqualified" I think this logic makes sense. I thought it was in the Haskell Report but I can't find it. I agree, though, that allowing qualified names on the LHS of an instance decl would make perfect sense. It'd be easy to implement too. Volunteers welcome. (A short GHC proposal would be kosher.) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14629#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC