Ticket #1735 (closed bug: fixed)

Opened 6 years ago

Last modified 4 years ago

unused binding changes program behaviour

Reported by: igloo Owned by: simonpj
Priority: normal Milestone: 6.12 branch
Component: Compiler Version: 6.8
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Difficulty: Unknown
Test Case: typecheck/should_run/T1735 Blocked By:
Blocking: Related Tickets:

Description

I'm not 100% sure this is a bug, but it's certainly surprising. If I add an unused function to my module:

#ifdef FOO
rigidTests :: Maybe (Maybe [YesNo])
rigidTests =
 mkTest [Elem "No"  []] (Just [No])
#endif

(mkTest has a type signature, and all the datatypes are plain old Haskell 98) then the behaviour of the program changes:

Without the function:

$ tar -zxf unused_bind_bug.tar.gz
$ cd unused_bind_bug
$ ghc -cpp --make Main
[1 of 6] Compiling SYBWC.Context    ( SYBWC/Context.hs, SYBWC/Context.o )
[2 of 6] Compiling SYBWC.Basics     ( SYBWC/Basics.hs, SYBWC/Basics.o )
[3 of 6] Compiling SYBWC.Instances  ( SYBWC/Instances.hs, SYBWC/Instances.o )
[4 of 6] Compiling State            ( State.hs, State.o )
[5 of 6] Compiling Xml              ( Xml.hs, Xml.o )
[6 of 6] Compiling Main             ( Main.hs, Main.o )
Linking Main ...
$ ./Main
Nothing

With the function:

$ tar -zxf unused_bind_bug.tar.gz
$ cd unused_bind_bug
$ ghc -cpp -DFOO --make Main
[1 of 6] Compiling SYBWC.Context    ( SYBWC/Context.hs, SYBWC/Context.o )
[2 of 6] Compiling SYBWC.Basics     ( SYBWC/Basics.hs, SYBWC/Basics.o )
[3 of 6] Compiling SYBWC.Instances  ( SYBWC/Instances.hs, SYBWC/Instances.o )
[4 of 6] Compiling State            ( State.hs, State.o )
[5 of 6] Compiling Xml              ( Xml.hs, Xml.o )
[6 of 6] Compiling Main             ( Main.hs, Main.o )
Linking Main ...
$ ./Main
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize' to increase it.

I suspect that the stack overflow is caused by my

instance (Xml a, Xml [a]) => Xml [a] where

hack to get around #1470 (and if so, that bug is more important to me).

This is with

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.8.0.20070923

but I had the same problem with 6.6.1.

Standalone testcase attached.

Attachments

unused_bind_bug.tar.gz Download (5.9 KB) - added by igloo 6 years ago.

Change History

Changed 6 years ago by igloo

Changed 6 years ago by igloo

  • milestone set to 6.8 branch

I still haven't investigated this properly, so it might want to be moved to 6.10 or closed.

Changed 6 years ago by simonmar

  • milestone changed from 6.8 branch to 6.8.3

investigate for 6.8.3

Changed 5 years ago by simonmar

  • owner set to simonpj

Changed 5 years ago by igloo

  • milestone changed from 6.8.3 to 6.10.1

Changed 5 years ago by simonpj

  • priority changed from normal to low
  • milestone changed from 6.10.1 to 6.12 branch

It's definitely that dodgy instance declaration. I can't quite say why it works sometimes and sometimes not, and I agree that is undesirable. But I can see it's very delicately balanced.

I'm not going to pursue this until I've fixed #1470

Simon

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 igloo

  • priority changed from low to normal

Still happens in the HEAD, although the failure is now

Main: <<loop>>

in the -DFOO case.

Changed 4 years ago by simonpj

  • status changed from new to closed
  • testcase set to typecheck/should_run/T1735
  • resolution set to fixed

This one has been in my to-do list for a long time, and I've finally gotten around to looking at it again. The key declarations in Xml.hs read thus:

class (Data XmlD a) => Xml a where ...

instance Xml String where ...

-- The Xml [a] context is a bit scary, but if we don't 
-- have it then GHC complains about overlapping instances
instance (Xml a, Xml [a]) => Xml [a] where ....

Wihtout the "scary" Xml [a] in the context, GHC 6.8 rejected the latter instance thus

Xml.hs:128:0:
    Overlapping instances for Xml [a]
      arising from the superclasses of an instance declaration
                   at Xml.hs:128:0
    Matching instances:
      instance [overlap ok] (Xml a) => Xml [a]
        -- Defined at Xml.hs:(128,0)-(136,68)
      instance [overlap ok] Xml String
        -- Defined at Xml.hs:(138,0)-(142,26)

But that got fixed when I fixed #1470; see Note [Recursive superclasses] in TcInstDcls. So now the program works fine without the scary bit, and with or without -DFOO.

If you have the scary bit, then it's unsurprising that things go badly wrong. The details are:

  • The superclass for the Xml [a] dictionary being constructed is gotten by superclass-selection from the Xml [a] dictionary passed in.
    $fXml dx dxs = MkD ($p2 dxs) ...
    
  • When the instance declaration is used, you get a recursive dictionary, thus
    d :: Xml [YesOrNo]
    d = $fXml[] d' d
    
  • So every Xml [a] dictionary has a superclass that is exactly bottom.

The odd behaviour of the unused definition arises thus:

  • It just so happens that the unused binding gives rise to the need for an XML [YesOrNo?] dictionary. It isn't used, but when the contraints simplifier needs a Data XMLD [YesOrNo] dictionary, it can get it from the (bogus) dictionary it has lying around.

If you write instance declarations like that, wierd stuff is going to happen to you. Closing this ticket!

Note: See TracTickets for help on using tickets.