[GHC] #9795: Debug.Trace.trace is too strict

GHC ghc-devs at haskell.org
Fri Feb 13 22:24:38 UTC 2015


#9795: Debug.Trace.trace is too strict
-------------------------------------+-------------------------------------
        Reporter:  jcpetruzza        |                   Owner:
            Type:  bug               |                  Status:  patch
        Priority:  normal            |               Milestone:  7.12.1
       Component:  libraries/base    |                 Version:  7.8.3
      Resolution:                    |                Keywords:
Operating System:  Unknown/Multiple  |            Architecture:
 Type of failure:  None/Unknown      |  Unknown/Multiple
      Blocked By:                    |               Test Case:
 Related Tickets:                    |                Blocking:
                                     |  Differential Revisions:  Phab:D654
-------------------------------------+-------------------------------------

Comment (by simonpj):

 Thomie is right, and Reid is (very unusually) off the mark,  unless I'm
 mistaken.

 `trace` really is defined (in `Debug.Trace` like this), just as the OP
 thought:
 {{{
 trace :: String -> a -> a
 trace string expr
   = unsafePerformIO $ do
     traceIO string
     return expr
 }}}
 The call to `traceIO` really does happen before `expr` is evaluated.

 The culprit is `traceIO`:
 {{{
 traceIO :: String -> IO ()
 traceIO msg = do
     withCString "%s\n" $ \cfmt -> do
      -- NB: debugBelch can't deal with null bytes, so filter them
      -- out so we don't accidentally truncate the message.  See Trac #9395
      let (nulls, msg') = partition (=='\0') msg
      withCString msg' $ \cmsg ->
       debugBelch cfmt cmsg
      when (not (null nulls)) $
        withCString "WARNING: previous trace message had null bytes" $
 \cmsg ->
          debugBelch cfmt cmsg
 }}}
 I'm not quite sure what those calls to `withCString` are doing, but I
 think they
 are strict in the string.  So if the message has bottoms in it (which is
 the case
 in this example) none of it will get printed.

 That is not really too bad; although it should be documented. After all,
 you
 can always write
 {{{
   trace ("in: " ++ show n) $
   trace ("out: " ++ show res) $
   res
 }}}
 and now you should see the first message even if you get stuck on the
 second.

 My conclusion: fix the documentation.  I'll add this to the documentation
 for
 `trace`:
 {{{
 The 'trace' function evaluates the message (i.e. the first argument)
 completely
 before printing it; so if the message is not fully defined, none of it
 will be printed.
 }}}
 OK?

 Simon

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


More information about the ghc-tickets mailing list