Thread overview
[Issue 7675] New: std.format needs better exception messages
Mar 09, 2012
Andrej Mitrovic
May 26, 2012
Andrej Mitrovic
May 26, 2012
Andrej Mitrovic
Jan 25, 2013
Andrej Mitrovic
May 22, 2013
Lukasz Wrzosek
May 22, 2013
Andrej Mitrovic
May 24, 2013
Lukasz Wrzosek
March 09, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7675

           Summary: std.format needs better exception messages
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody@puremagic.com
        ReportedBy: andrej.mitrovich@gmail.com


--- Comment #0 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2012-03-08 17:53:14 PST ---
import std.string;

void main()
{
    string res = format("%s %s", 1);
}

std.format.FormatException@std\format.d(62): format error

format() should verify that the count of parameters matches the format specifier and give a nice error message like this:

std.format.FormatException@std\format.d(62): format error: Expected 2
parameters, got 1.

format() is one of the most used functions in Phobos so I think this is pretty
important.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7675



--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2012-05-26 09:54:34 PDT ---
If anyone else is annoyed by this you can use a workaround like this:

/** Workaround for Issue 7675 - std.format needs better exception messages */
string safeFmt(string file = __FILE__, int line = __LINE__, T...)(string fmt, T
args)
{
    auto specCount = count(fmt, "%s");
    enforce(specCount == T.length,
            new Exception(format("Arg count %s doesn't match spec count %s.",
T.length, specCount), file, line));
    return format(fmt, args);
}

That implies using %s exclusively and it only throws on argument count mismatch, but it's still a shitload better than "Error occurred somewhere, have fun debugging!".

Throwing exceptions in Phobos with no information on what went wrong should be *banned*.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7675


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #2 from bearophile_hugs@eml.cc 2012-05-26 11:57:34 PDT ---
(In reply to comment #1)

>     enforce(specCount == T.length,
>             new Exception(format("Arg count %s doesn't match spec count %s.",
> T.length, specCount), file, line));

Andrei wants formatted printing to be sloppy, so currently this doesn't raise an error:

import std.string;
void main() {
    string res = format("%s ", 1, 2);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 26, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7675



--- Comment #3 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2012-05-26 12:42:38 PDT ---
(In reply to comment #2)
> Andrei wants formatted printing to be sloppy, so currently this doesn't raise an error..

Right, but the OP code does raise an exception except it gives absolutely no information whatsoever on what went wrong. Reading a stack trace of a dozen template instantiations doesn't help either.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7675


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |WORKSFORME


--- Comment #4 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-01-24 16:11:25 PST ---
The situation seems to be better now:

import std.string;
void main()
{
    string res = format("%s %s", 1);
}

> std.format.FormatException@D:\dmd-git\dmd2\windows\bin\..\..\src\phobos\std\format.d(431): Orphan format specifier: %%s %s

Slightly confusing message, as it thought it was going to print '%s' but it prints the entire string.

And the other message:

import std.string;
void main()
{
    string res = format("%s %s", 1, 2, 3);
}

> std.format.FormatException@D:\dmd-git\dmd2\windows\bin\..\..\src\phobos\std\string.d(2536): Orphan format arguments: args[2..3]

I'm quite satisfied that this was implemented. Although the stack trace still sucks as I've yet to get proper line numbers.

But at least I don't have to count the specifiers in a wrapper function, I just have to catch FormatExceptions:

string safeFmt(string file = __FILE__, size_t line = __LINE__, Args...)(string
fmt, Args args)
{
    try
    {
        return format(fmt, args);
    }
    catch (FormatException exc)
    {
        exc.file = file;
        exc.line = line;
        throw exc;
    }
}

void main()
{
    auto x = safeFmt("%s", 1, 2);
}

How great is that?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 22, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7675


Lukasz Wrzosek <luk.wrzosek@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |luk.wrzosek@gmail.com


--- Comment #5 from Lukasz Wrzosek <luk.wrzosek@gmail.com> 2013-05-22 10:33:44 PDT ---
Why this sample compiles fine if it always frows an exception ?

import std.string;

void main()
{
    string res = format("%s %s", 1);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 22, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7675



--- Comment #6 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-05-22 14:39:28 PDT ---
(In reply to comment #5)
> Why this sample compiles fine if it always throws an exception ?

Because the string argument is passed at runtime.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 24, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7675



--- Comment #7 from Lukasz Wrzosek <luk.wrzosek@gmail.com> 2013-05-24 05:50:11 PDT ---
I know that already, but why it was written like that?
It would be useful to have this kind of error thrown at compile time, wouldn't
it"

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------