[GHC] #8854: Missing class method not caught at compile time, program freezes when missing method is called.

#8854: Missing class method not caught at compile time, program freezes when missing method is called. ----------------------------------+---------------------------------- Reporter: RaminHAL9001 | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Keywords: | Operating System: Linux Architecture: x86_64 (amd64) | Type of failure: Runtime crash Difficulty: Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #7633 | ----------------------------------+---------------------------------- I created a type class where two of four functions must be satisfied for a minimal complete definition. GHC did not catch an instance where the minimal complete definition was not satisfied, the program compiled without an error or warning. When running the compiled program it would freeze when calling the missing method. Also when running the program in GHCi and stepping up to the use of the missing method, GHCi would freeze before reaching the missing function. This made it very difficult to debug. It '''did not''' throw a "NoMethodError" exception, and there '''was no''' segment violation caught by the operating system, nor does the program terminate with the "<<loop>>" message output on the command line. Compiling with language extensions: {{{ -XTemplateHaskell -XScopedTypeVariables -XRankNTypes -XMultiParamTypeClasses -XFunctionalDependencies -XFlexibleInstances -XFlexibleContexts -XDeriveDataTypeable }}} Using compiler flags: {{{ -prof -fprof-auto -threaded -Wall -fno-warn-name-shadowing -fno-warn- unused-do-bind -fno-warn-auto-orphans }}} '''To Reproduce the Issue''' I tried to reproduce the issue with a miniature program that isolates the problem, but GHC successfully detects a problem and terminates with the "<<loop>>" message written on the command line. My program is much larger and simply froze. However the code I wrote looks similar to the following situation... First I tried this, which gave me no problems at all: {{{ class A x where f1 :: x f1 = f2 f2 :: x f2 = f1 }}} We have two functions f1 and f2, if f1 is not defined it defaults to f2, if f2 is not defined it defaults to f1, so you must define either f1 or f2, or you could also define both. Then I add two more methods: {{{ class A x where f1 :: x f1 = f2 f2 :: x f2 = f1 g1 :: x g1 = g2 g2 :: x g2 = g1 }}} Just like with f1 f2, the g1 g2 functions each use their counterpart to define their default method. But this caused a huge problem. The minimal complete definition should be (f1 | f2) & (g1 | g2), but the compiler does not report any warning when I have not satisfied the minimal complete definition. Maybe one of my compiler flags disabled a would-be warning, I don't know yet. This was a red-flag to me, but I went on to test my program. As it turns out, there was a place in my code where I forgot to write an instance for g1 or g2 but I had not realize it. I only found out when I ran my test program and it froze. No "unsatisfied method" exception, not segment violations, it just froze. Although the program was still running and consuming a small amount of CPU resources, and I could cancel with CTRL-C in the command line. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8854 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8854: Missing class method not caught at compile time, program freezes when missing method is called. ----------------------------------+---------------------------------- Reporter: RaminHAL9001 | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 (amd64) Type of failure: Runtime crash | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: #7633 ----------------------------------+---------------------------------- Comment (by simonpj): If you specify the minimal complete definition, using the MINIMAL pragma (which is part of 7.8, but not 7.6) then it should warn. If it doesn't, that's a bug. Can you give the complete source code for a program that exhibits the bug... if we can't reproduce it we can't fix it. Thanks Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8854#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

If you specify the minimal complete definition, using the MINIMAL pragma (which is part of 7.8, but not 7.6) then it should warn. If it doesn't,
#8854: Missing class method not caught at compile time, program freezes when missing method is called. ----------------------------------+---------------------------------- Reporter: RaminHAL9001 | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 (amd64) Type of failure: Runtime crash | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: #7633 ----------------------------------+---------------------------------- Comment (by RaminHAL9001): My full source code repository is here: https://github.com/RaminHAL9001/dao You can clone the repository and just run "make" on Linux, it should compile fine with GHC 7.6.1. It will produce two executable programs, "./dao" and "./debug/test". In the "Dao.Interpreter" module, there is an instance: {{{ instance HasRandGen [Comment] where { randO = return []; defaultO = return []; } }}} If you remove the "defaultO" instance and re-compile, that should reproduce the bug, This was the exact instance I had not defined that was causing it to freeze. To run the test suite to cause the error to occur, change to the "debug" directory and run the "test" program. It works a bit like QuickCheck, but you can specify random seed values on the command line to produce the same random test cases every time, for example: {{{ ./test 8 14 }}} I found seeds 8 and 14 crashed reliably, both compiled and in GHCi. But I don't know if the random number generator will produce the same test cases on your hardware as it will on mine so you may have to run a few dozen tests before you find one that freezes. {{{ ./test $(seq 1 100) }}} The source code is under active development, so things may change. However for the time being I don't expect there to be any changes to the part of the code that lets you reproduce the bug. I did see the {-# MINIMAL #-} pragma in #7633, but I am using GHC 7.6.1 for now. Replying to [comment:1 simonpj]: that's a bug. Can you give the complete source code for a program that exhibits the bug... if we can't reproduce it we can't fix it.
Thanks
Simon
-- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8854#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8854: Missing class method not caught at compile time, program freezes when missing method is called. ----------------------------------+---------------------------------- Reporter: RaminHAL9001 | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: invalid | Keywords: Operating System: Linux | Architecture: x86_64 (amd64) Type of failure: Runtime crash | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: #7633 ----------------------------------+---------------------------------- Changes (by simonpj): * status: new => closed * resolution: => invalid Comment: Oh well, that's easy! This situation is precisely what the MINIMAL pragma is for. There is not, and never was, the slightest guarantee that anything else will work. If you get `<<loop>>` you are just lucky! It's not a bug in 7.6; it just a feature that doesn't exist, but now does. Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8854#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC