[GHC] #15125: Typeclass instance selection depends on the optimisation level

GHC ghc-devs at haskell.org
Sun May 6 10:24:52 UTC 2018


#15125: Typeclass instance selection depends on the optimisation level
-------------------------------------+-------------------------------------
        Reporter:  nicuveo           |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.2.2
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Description changed by nicuveo:

Old description:

> (See the attached files for a minimal case.)
>
> A file A defines a typeclass, and gives an incoherent instance for all
> types a, and exports a function relying on said typeclass. A file B
> defines some data types, makes them specific instances of that class.
> Which instance ends up being picked depends on the optimisation level
> they're compiled with.
>
> //A.hs//
> {{{#!hs
> class A a where
>   someValue :: a -> Maybe Int
>
> instance {-# INCOHERENT #-} A a where
>   someValue = const Nothing
>
> getInt :: A a => a -> Int
> getInt x = fromMaybe 0 $ someValue x
> }}}
>
> //B.hs//
> {{{#!hs
> data B = B Int
>
> instance A B where
>   someValue (B x) = Just x
>
> getBInt :: Int
> getBInt = getInt $ B 42
> }}}
>

> //Main.hs//
> {{{#!hs
> main = print getBInt
> }}}
>
> **Upon compiling with -O0, this prints 42; upon compiling with -O2, this
> print 0.**
>
> (Interestingly, if the redundant class constraint is removed from getInt,
> then it always prints 0.)

New description:

 (See the attached files for a minimal case.)

 A file A defines a typeclass, and gives an incoherent instance for all
 types a, and exports a function relying on said typeclass. A file B
 defines some data types, makes them specific instances of that class, and
 uses the function defined in A. Which instance ends up being picked for B
 depends on the optimisation level those files are compiled with.

 //A.hs//
 {{{#!hs
 class A a where
   someValue :: a -> Maybe Int

 instance {-# INCOHERENT #-} A a where
   someValue = const Nothing

 getInt :: A a => a -> Int
 getInt x = fromMaybe 0 $ someValue x
 }}}

 //B.hs//
 {{{#!hs
 data B = B Int

 instance A B where
   someValue (B x) = Just x

 getBInt :: Int
 getBInt = getInt $ B 42
 }}}


 //Main.hs//
 {{{#!hs
 main = print getBInt
 }}}

 **Upon compiling with -O0, this prints 42; upon compiling with -O2, this
 prints 0.**

 (Interestingly, if the redundant class constraint is removed from getInt,
 then it always prints 0.)

--

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15125#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list