Ticket #1465 (closed bug: fixed)

Opened 6 years ago

Last modified 4 years ago

Type errors due to different package versions are a bit cryptic

Reported by: guest Owned by:
Priority: normal Milestone: 6.8.1
Component: Compiler (Type checker) Version: 6.6.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Difficulty: Moderate (less than a day)
Test Case: tcfail182, bug1465, mod180 Blocked By:
Blocking: Related Tickets:

Description

Users of xmonad who've compiled one dependent library against X11 1.2, and then update X11, and attempt to recompile xmonad against the new X11 1.2.2, get a cryptic type error:

    Couldn't match expected type `Graphics.X11.Xlib.Types.Display'
              against inferred type `Display'

Perhaps non-local types should be printed with their package name and version, which would clarify this error. Something like:

    Couldn't match expected type `X11-1.2: Graphics.X11.Xlib.Types.Display'
              against inferred type `X11-1.2.2: Display'

Change History

Changed 6 years ago by simonmar

  • type changed from feature request to bug
  • milestone set to 6.8

Yes, this is really a bug, so I'm marking it as such. We thought about it, and then promptly forgot about it, when we added support for multiple versions of packages,

I don't think we want to always add the package name. What is a "non-local type"? One that comes from another package? Then Int is non-local too. My suggestion would be to add the package name if the types that fail to unify have the same qualified name. Perhaps add an option to include the package names unconditionally.

Changed 6 years ago by simonpj

  • testcase set to tcfail182

Excellent suggestion. I've arranged to print more info if the two types have the same occurrence name, since some confusion may then occur. For example:

module Foo where

import qualified Prelude
import Prelude hiding( Maybe )

data Maybe a = Foo

f :: Prelude.Maybe a -> Int
f Foo = 3

now produces the error:

Foo.hs:11:2:
    Couldn't match expected type `Prelude.Maybe a'
	   against inferred type `Maybe a1'
      `Prelude.Maybe' is defined in module `Data.Maybe' from package `base'
      `Maybe' is defined in this module
    In the pattern: Foo
    In the definition of `f': f Foo = 3

Can you check that your use-case is also improved, and if so close the bug?

Simon

Changed 6 years ago by simonmar

I'm not sure about the "defined in module" bit. Won't this give rise to things like "Int is defined in module GHC.Base", which could confuse the average user who doesn't have a clue what GHC.Base is, and finds that it isn't even documented? We should say where the module is imported from, not defined.

Changed 6 years ago by simonpj

Trouble is, that's just the problem 'guest' reported. It's not enough to say that Display imported from M does not match Display imported from Y! We want to say where Display originally came from.

We could readily suppress the module name if the package names are different though. That way we'd only show the defining modules if both names came from the same package. Would that be better?

Simon

Changed 6 years ago by Isaac Dupree

That sounds reasonable to me. Because, trouble is, type-identity in Haskell is defined by the identity of the defining module... although it would be just as accurate to say that the entire set of package×modules it's exported from define its identity (from the point of view of the type's user), and those could be listed or one of them chosen. Except ... a type's name doesn't necessarily even have to be exported anywhere for it to be causing type errors (admittedly a bad practice to be exporting things whose type signature cannot be written externally).

Changed 6 years ago by simonmar

Trouble is, that's just the problem 'guest' reported. It's not enough to say that Display imported from M does not match Display imported from Y! We want to say where Display originally came from.

What distinguishes these two types is the package they came from, not the defining module. In the original example, the defining modules were the same. GHC should never report the defining module of a name, because that breaks abstraction, and it isn't useful: the defining module might be unexposed, and undocumented. (I think we already report original names when the name in question is not in scope at all, perhaps this should be fixed too).

I suggest that when the unqualified names of the types that failed to unify are the same, we report the package names, since this is the case that is likely to be confusing to the user. It's probably useful to report where the types were imported from too.

Changed 6 years ago by simonpj

I've arranged (I believe already committed) that we report the package names UNLESS two type constructors with the same occurrence name come from the same package -- and only then report the module name.

Simon

Changed 6 years ago by Isaac Dupree

Reporting the originating package may prove more difficult/abstraction-breaking once packages can re-export types from other packages (the same way we have difficulty with modules that re-export the types from other modules) -- just a note for future reference, perhaps.

Changed 6 years ago by simonmar

  • status changed from new to closed
  • difficulty changed from Easy (1 hr) to Moderate (1 day)
  • resolution set to fixed
  • testcase changed from tcfail182 to tcfail182, bug1465, mod180

Fixed:

Thu Sep  6 10:37:44 BST 2007  Simon Marlow <simonmar@microsoft.com>
  * FIX #1465, error messages could sometimes say things like "A.T doesn't match A.T"

Changed 6 years ago by igloo

  • milestone changed from 6.8 branch to 6.8.1

Changed 5 years ago by simonmar

  • architecture changed from Unknown to Unknown/Multiple

Changed 5 years ago by simonmar

  • os changed from Unknown to Unknown/Multiple

Changed 4 years ago by simonmar

  • difficulty changed from Moderate (1 day) to Moderate (less than a day)
Note: See TracTickets for help on using tickets.