Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added writer overload of toString to Appender #6235

Merged
merged 1 commit into from
Mar 13, 2018

Conversation

JackStouffer
Copy link
Member

No description provided.

@dlang-bot
Copy link
Contributor

dlang-bot commented Feb 28, 2018

Thanks for your pull request, @JackStouffer!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

std/array.d Outdated
// different reserve lengths because each element in a
// non-string-like array uses two extra characters for `, `
static if (isSomeString!A)
app.reserve(_data.arr.length + 10);
Copy link
Member

@n8sh n8sh Feb 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just _data.arr.length if the source is a string?

EDIT: Ah nevermind I see, you also add typeof(this).stringof and parentheses around the result. But 10 chars means the array will always be too short, since it is just the length of "Appender()" and doesn't include "!something".

@JackStouffer
Copy link
Member Author

There's some sort of odd call to appender's toString happening somewhere in conv.to. Currently investigating.

@JackStouffer
Copy link
Member Author

I found a bug in hasToString that I need help fixing. @n8sh @wilzbach

Consider

import std.format;
import std.range;

struct A(T)
{
    string toString() const { return ""; }
    void toString(W)(ref W w) const { put(w, ""); }
}

struct B(T)
{
    string toString()() const { return ""; }
    void toString(W)(ref W w) const { put(w, ""); }
}

void main()
{
    pragma(msg, hasToString!(A!(int), char)); // 1
    pragma(msg, hasToString!(B!(int), char)); // 5
}

It has to do with this line

static assert(ParameterStorageClassTuple!(T.toString!(S))[0] == ParameterStorageClass.ref_);}

Because the first toString overload in A is not a template but a function, the attempted instantiation of the toString template inside hasToString always fails despite the fact that there is an existing toString template.

@JackStouffer
Copy link
Member Author

This needs to be fixed before we release 2.079

@JackStouffer
Copy link
Member Author

Needs #6247

@JackStouffer
Copy link
Member Author

Ready to go.

std/array.d Outdated
// Even though the Appender might represent a string,
// make a copy of the data anyway because we don't want
// manipulations of the toString result to change the
// data of the Appender
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the element type is immutable how could manipulations of the toString result change the data of the Appender?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm, you're right, I was thinking more of the char[] case. In any case, the code remains the same regardless to keep it dry and to use the speedup of Appender.

I'll just remove the comment.

Copy link
Member

@wilzbach wilzbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM + a few nits

std/array.d Outdated
auto spec = singleSpec("%s");
// different reserve lengths because each element in a
// non-string-like array uses two extra characters for `, `
static if (isSomeString!A)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW we wanted to deprecate this trait...

#5284, #5137

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSomeString is far too ubiquitous to deprecate IMO. Johnathan already modified it to not recognize enums, which I think was the main issue.

std/array.d Outdated
// Even though the Appender might represent a string,
// make a copy of the data anyway because we don't want
// manipulations of the toString result to change the
// data of the Appender
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also support const(string) toString()() const ...

std/array.d Outdated
// different reserve lengths because each element in a
// non-string-like array uses two extra characters for `, `
static if (isSomeString!A)
app.reserve(_data.arr.length + 15);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appender!(int[])() has 18 character, so maybe + 20 or +25 or maybe even better with Unqual!(typeof(this)).stringof.length + 2?

std/array.d Outdated
static if (isSomeString!A)
app.reserve(_data.arr.length + 15);
else
app.reserve((_data.arr.length * 3) + 15);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I assume this is the conservative estimate that of X, being three characters which does make sense, though I think it would be nice to add a comment for future readers about this conservative estimate.

std/array.d Outdated
*/
string toString() const
{
auto app = appender!string();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory we could also do const(string) toString()() const { return app.data } for appender!string, but that's a potential optimization for the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still need to add Unqual!(typeof(this)).stringof

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. Though that could be solved by allowing toString to return a range, but that's a story for a different PR.

@JackStouffer
Copy link
Member Author

That weird std.conv error is showing up again. I'll fix this when I get a chance.

@JackStouffer JackStouffer force-pushed the appender-tostring branch 2 times, most recently from 32a28a3 to ada7d5f Compare March 13, 2018 12:36
@@ -7102,7 +7102,7 @@ public: // Public API continues
Returns:
length of grapheme cluster
+/
size_t graphemeStride(C)(const scope C[] input, size_t index)
size_t graphemeStride(C)(const scope C[] input, size_t index) @safe pure
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After going all the way down the rabbit hole, I found out that due to some compiler bug, DMD marked this as @system when it was instantiated from std.formatRange from std.conv.textImpl. No idea why. Manually adding the attributes fixes the whole issue.

@dlang-bot dlang-bot merged commit 36edc8b into dlang:master Mar 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants