Skip to content

Commit

Permalink
Merge pull request #6207 from JackStouffer/issue18486
Browse files Browse the repository at this point in the history
Fix Issue 7879 - format of const class with non const toString()
  • Loading branch information
wilzbach committed Feb 28, 2018
2 parents 5c01f5a + ab93c46 commit 93dc74b
Showing 1 changed file with 61 additions and 3 deletions.
64 changes: 61 additions & 3 deletions std/format.d
Expand Up @@ -3787,8 +3787,6 @@ private void formatValueImpl(Writer, T, Char)(auto ref Writer w, T val, const re
if (is(T == class) && !is(T == enum))
{
enforceValidFormatSpec!(T, Char)(f);
// TODO: Change this once toString() works for shared objects.
static assert(!is(T == shared), "unable to format shared objects");

// TODO: remove this check once `@disable override` deprecation cycle is finished
static if (__traits(hasMember, T, "toString") && isSomeFunction!(val.toString))
Expand All @@ -3799,7 +3797,20 @@ if (is(T == class) && !is(T == enum))
put(w, "null");
else
{
static if (hasToString!(T, Char) > 1 || (!isInputRange!T && !is(BuiltinTypeOf!T)))
static if ((is(T == immutable) || is(T == const) || is(T == shared)) && hasToString!(T, Char) == 0)
{
// issue 7879, remove this when Object gets const toString
static if (is(T == immutable))
put(w, "immutable(");
else static if (is(T == const))
put(w, "const(");
else static if (is(T == shared))
put(w, "shared(");

put(w, typeid(Unqual!T).name);
put(w, ')');
}
else static if (hasToString!(T, Char) > 1 || !isInputRange!T && !is(BuiltinTypeOf!T))
{
formatObject!(Writer, T, Char)(w, val, f);
}
Expand Down Expand Up @@ -3891,6 +3902,53 @@ if (is(T == class) && !is(T == enum))
formatTest( new C5([0, 1, 2]), "[0, 1, 2]" );
}

// outside the unittest block, otherwise the FQN of the
// class contains the line number of the unittest
version(unittest)
{
private class C {}
}

// issue 7879
@safe unittest
{
const(C) c;
auto s = format("%s", c);
assert(s == "null");

immutable(C) c2 = new C();
s = format("%s", c2);
assert(s == "immutable(std.format.C)");

const(C) c3 = new C();
s = format("%s", c3);
assert(s == "const(std.format.C)");

shared(C) c4 = new C();
s = format("%s", c4);
assert(s == "shared(std.format.C)");
}

// https://issues.dlang.org/show_bug.cgi?id=7879
@safe unittest
{
class F
{
override string toString() const @safe
{
return "Foo";
}
}

const(F) c;
auto s = format("%s", c);
assert(s == "null");

const(F) c2 = new F();
s = format("%s", c2);
assert(s == "Foo", s);
}

// ditto
private void formatValueImpl(Writer, T, Char)(auto ref Writer w, T val, const ref FormatSpec!Char f)
if (is(T == interface) && (hasToString!(T, Char) || !is(BuiltinTypeOf!T)) && !is(T == enum))
Expand Down

0 comments on commit 93dc74b

Please sign in to comment.