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

Fix issue 19003: don't call toString on T.init #6594

Conversation

FeepingCreature
Copy link
Contributor

Avoid actually calling toString when speculatively formatting to check for format exceptions.

Args.init is not a constructed value; hence it is not safe to call methods on it.

Two-step solution:

  1. avoid actually calling toString when writing into NullSink (why bother?)

  2. call formattedWrite to write into NullSink in checkFormatException.

@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @FeepingCreature! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the annotated coverage diff directly on GitHub with CodeCov's browser extension
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
19003 normal format!"" breaks with structs containing invariants violated in .init

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub fetch digger
dub run digger -- build "master + phobos#6594"

@FeepingCreature FeepingCreature force-pushed the fix/Issue-19003-dont-call-tostring-on-type-init branch from f134628 to 1f801df Compare June 18, 2018 14:04
@FeepingCreature
Copy link
Contributor Author

ping

1 similar comment
@FeepingCreature
Copy link
Contributor Author

ping

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Looks good. I'd put the ThenStatements on their own lines but since CircleCI is green i suppose it's good.

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented Jun 25, 2018

I didn't want the change to become too verbose; this way it's structurally easy to parse. I don't know how else to do it, given that the final else should still always run.

std/format.d Outdated

invariant { assert(this.i); }

this(int i) @safe in { assert(i); } body { this.i = i; }
Copy link
Member

Choose a reason for hiding this comment

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

s/body/do/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@FeepingCreature FeepingCreature force-pushed the fix/Issue-19003-dont-call-tostring-on-type-init branch from 1f801df to c10999e Compare June 25, 2018 11:26
@FeepingCreature
Copy link
Contributor Author

ping

@n8sh
Copy link
Member

n8sh commented Jul 9, 2018

  1. avoid actually calling toString when writing into NullSink (why bother?)

Perhaps because someone is calling it for a side-effect (like timing a formatting operation) or because someone is calling it to make sure that the code runs. Neither of those happen if the code is blocked out with static if. If NullSink has any purpose at all, then you probably shouldn't be doing this.

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented Jul 9, 2018

It seemed kind of redundant to implement a DontCallToStringSink { NullSink ns; alias ns this; }, but sure.

The important thing is I really don't want to add a template parameter and hunt it all the way through the toStrings, especially since it's a public API.

@n8sh
Copy link
Member

n8sh commented Jul 10, 2018

It's not obvious at a cursory glance: can you explain why the "invalid format" check still works with the code behind static if (!noop) not being called or compiled?

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented Jul 10, 2018

The "invalid format" check has largely nothing to do with toString(); rather, it checks for the format string being valid, whose parsing is done by formattedWrite and friends. However, like the Nullable issue but more so, this relies on T.init being a valid value that you can call methods on. (I'm increasingly becoming convinced that the case of structs with invalid T.init was never intended - so I really don't understand why you can @disable this() in the first place...) That said, the failure of T.init.toString() does not tell us much about formatting an arbitrary T - a toString() that simply always throws an exception is not a very common problem. So this PR assumes that invalid T.inits are more common than toStrings that always throw.

@FeepingCreature FeepingCreature force-pushed the fix/Issue-19003-dont-call-tostring-on-type-init branch from c10999e to d6c41a3 Compare July 11, 2018 13:52
@FeepingCreature
Copy link
Contributor Author

@n8sh Replaced NullSink with NoOpSink, which is a copypaste of NullSink.

@n8sh n8sh added the 72h no objection -> merge The PR will be merged if there are no objections raised. label Jul 15, 2018
@FeepingCreature FeepingCreature force-pushed the fix/Issue-19003-dont-call-tostring-on-type-init branch from d6c41a3 to be8dace Compare July 18, 2018 07:34
@FeepingCreature
Copy link
Contributor Author

oops, tiny fix - readded a comment I accidentally removed

@FeepingCreature
Copy link
Contributor Author

@n8sh note that it won't merge despite that label due to the lack of approving review. What do?

@Geod24
Copy link
Member

Geod24 commented Jul 19, 2018

Well there is also a CircleCI failure

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented Jul 19, 2018

Yeah, that sucks for CircleCI.

It has nothing to do with this PR though.

edit: Oh you mean it won't merge cause a required check is failing?

Well that sucks. It just says "review required" though and "merging can be performed with one approving review."

@Geod24
Copy link
Member

Geod24 commented Jul 19, 2018

It has nothing to do with this PR though.

A rebase would help then

edit: Oh you mean it won't merge cause a required check is failing?

Yes, and people are less eager to review a PR which is red.

@FeepingCreature
Copy link
Contributor Author

FeepingCreature commented Jul 19, 2018

A rebase would help then

Would it? It's been red everywhere for about a week at this point.

edit: fine, let's try again

edit: it failed again, oh no

@FeepingCreature FeepingCreature force-pushed the fix/Issue-19003-dont-call-tostring-on-type-init branch from be8dace to 902468f Compare July 19, 2018 12:46
@wilzbach
Copy link
Member

Would it? It's been red everywhere for about a week at this point.

No need to waste resources on this. See #ci or check #6626

@wilzbach
Copy link
Member

Merged the CircleCi PR and restarted it. It should pass now. Jenkins is still a PITA, but we're planning to switch to Buildkite.
Unfortunately for now Buildkite doesn't offer an easy way to have public logs, but (1) it's passing and (2) I send out an invite to @FeepingCreature which should allow him to view the logs and restart a build if it should ever fail in the future.

@dlang-bot dlang-bot merged commit 43becea into dlang:master Jul 19, 2018
@FeepingCreature
Copy link
Contributor Author

yay!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
72h no objection -> merge The PR will be merged if there are no objections raised. auto-merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants