Opened 10 years ago

Closed 10 years ago

Last modified 4 years ago

#3303 closed merge (fixed)

Allow multi-line deprecation messages.

Reported by: duncan Owned by: igloo
Priority: high Milestone: 6.12.1
Component: Compiler Version: 6.10.2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: parser/should_compile/T3303
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

Sometimes one line just isn't enough. There's two related issues, pretty source code and pretty warning messages.

It is a bit annoying when a DEPRECATED pragma stretches on past 80-100 columns or whatever. Does the ordinary multi-line Haskell string syntax work in this situation? Even if it does it's not useful in practice due to the cpp-incompatibility, and because it's a pragma, we cannot use the normal ++ trick.

The other is presenting multi-line error messages to the user. Sometimes we want to present more info, like not just what the alternative is but for example when the alternative was added and when the deprecated thing will be removed.

In Cabal for example we've got ugly hack:

{-# DEPRECATED defaultUserHooks
     "Use simpleUserHooks or autoconfUserHooks, unless you need Cabal-1.2\n             compatibility in which case you must stick with defaultUserHooks" #-}

Yes it's really that wide :-)

Reformatted:

{-# DEPRECATED defaultUserHooks
     "Use simpleUserHooks or autoconfUserHooks, unless you \
      need Cabal-1.2\n             compatibility in which \
      case you must stick with defaultUserHooks" #-}

Note the silly "\n " to make the multi-line message line up ok in current ghc versions.

To allow embedded '\n' more sensibly, it just needs a slight tweak in the rendering. Split the message into lines and then use hsep or equivalent. That way we get correct indenting for free.

I'm not sure how long single-line messages get printed, but Cabal solves this problem for its error messages by re-wrapping text, though it also respects embedded newlines (to force line breaks or paragraph breaks).

-- | Wraps text to the default line width. Existing newlines are preserved.
wrapText :: String -> String
wrapText = unlines
         . concatMap (map unwords
                    . wrapLine 79
                    . words)
         . lines

-- | Wraps a list of words to a list of lines of words of a particular width.
wrapLine :: Int -> [String] -> [[String]]
wrapLine width = wrap 0 []
  where wrap :: Int -> [String] -> [String] -> [[String]]
        wrap 0   []   (w:ws)
          | length w + 1 > width
          = wrap (length w) [w] ws
        wrap col line (w:ws)
          | col + length w + 1 > width
          = reverse line : wrap 0 [] (w:ws)
        wrap col line (w:ws)
          = let col' = col + length w + 1
             in wrap col' (w:line) ws
        wrap _ []   [] = []
        wrap _ line [] = [reverse line]

There's also a more sophisticated version of this using the Doc type in the gtk2hs code gen utils. It has a parameter for the line width and handles prefix text on the first line.

Attachments (1)

fix-deprecation-formatting.dpatch (1.1 KB) - added by duncan 10 years ago.

Download all attachments as: .zip

Change History (12)

comment:1 Changed 10 years ago by duncan

On a similar topic, it's annoying not being able to control whether a type or identically named constructor is being deprecated. Consider:

data Foo = Foo ...

This is a very common idiom. But now we want to switch to smart constructors

foo :: ... -> Foo

and eventually stop exporting the constructor Foo. But we cannot specify just the constructor, only both. According to the user guide the workaround would be to have a module that imports one but not the other, however while that's possible for the type it's not possible for the constructor.

How about

{-# DEPRECATED constructor Foo "use `foo' instead" #-}

and while we're at it, might as well have

{-# DEPRECATED type Foo "..." #-}

leaving the unqualified case meaning both as it does now.

comment:2 Changed 10 years ago by simonpj

difficulty: Unknown

Concerning line wrapping, it's not clear that you want GHC to re-wrap your text at arbitrary places. You might care where the line breaks are. How about this: instead of giving one string, you can instead give a list of strings, which are displayed on successive lines. So input is:

{-# DEPRECATED defaultUserHooks
     ["Use simpleUserHooks or autoconfUserHooks, unless you need Cabal-1.2"
     , "compatibility in which case you must stick with defaultUserHooks"]
  #-}

The output would look as you'd expect. This is nice because it's backward compatible, and deals with points from the original report.

Concerning constructors vs types, the very same thing comes up with fixity declarations, at least when you use GHC's ability to have infix type constructors:

  infix 4 :+:

I'd be happy with a disambiguating prefix constructor, type, or class; at least when there was ambiguity. That means making constructor a new special_id, but it wouldn't be a keyword except in these two special situations, like other special_ids.

Comments?

Simon

comment:3 Changed 10 years ago by igloo

Milestone: 6.12.1

comment:4 Changed 10 years ago by igloo

Owner: set to igloo

comment:5 Changed 10 years ago by igloo

Resolution: fixed
Status: newclosed

I've fixed the original issue:

Wed Aug 12 19:59:12 BST 2009  Ian Lynagh <igloo@earth.li>
  * Add support for multi-line deprecated pragmas; trac #3303

and filed the other one as #3427.

comment:6 Changed 10 years ago by duncan

Resolution: fixed
Status: closedreopened

The formatting of deprecation pragmas now accidentally includes Haskell list syntax.

This pragma

module Foo
{-# DEPRECATED
      ["You are using the old package `base' version 3.x."
      ,"Future GHC versions will not support base version 3.x. You"
      ,"should update your code to use the new base version 4.x."]
  #-} where

gives this warning message:

Bar.hs:1:0:
    Warning: Module `Foo' is deprecated:
                 [You are using the old package `base' version 3.x.,
                  Future GHC versions will not support base version 3.x. You,
                  should update your code to use the new base version 4.x.]

Changed 10 years ago by duncan

comment:7 Changed 10 years ago by duncan

With the attached patch it looks like:

Foo.hs:1:0:
    Warning: Module `Prelude' is deprecated:
               You are using the old package `base' version 3.x.
               Future GHC versions will not support base version 3.x. You
               should update your code to use the new base version 4.x.

comment:8 Changed 10 years ago by simonpj

Thanks! I'm validating now.

comment:9 Changed 10 years ago by simonpj

Priority: normalhigh
Status: reopenednew
Type: bugmerge

I've pushed the patch. Ian pls merge

Simon

comment:10 Changed 10 years ago by igloo

Resolution: fixed
Status: newclosed
Type of failure: None/Unknown

Merged:

Sun Nov 15 15:56:17 GMT 2009  Duncan Coutts <duncan@well-typed.com>
  * Fix formatting of module deprecation/warning messages
  Ignore-this: a41444bdda003aee4412eb56a0e7d052
  It was accidentally using list syntax. Fixes #3303 again.

comment:11 Changed 4 years ago by thomie

Test Case: parser/should_compile/T3303

In commit bf510aa86f3161c981b3432d43417874c38adf8f:

Author: Ian Lynagh <igloo@earth.li>
Date:   Wed Aug 12 18:57:43 2009 +0000

    Add a test for #3303: multiline deprecated warnings
Note: See TracTickets for help on using tickets.