-
-
Notifications
You must be signed in to change notification settings - Fork 702
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
[Breaking] Deprecate alias get this
in Nullable.
#7060
[Breaking] Deprecate alias get this
in Nullable.
#7060
Conversation
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 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 referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf 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#7060" |
alias get this
in Nullable.alias get this
in Nullable.
61a7ad9
to
95246af
Compare
alias get this
in Nullable.alias get this
in Nullable.
d46b878
to
9afa647
Compare
It being a breaking change worries me. How about introducing a new optional type that doesn't have this issue and deprecating Nullable? |
Re deprecation, I could try to straight up disable it and see if anything breaks in buildkite; that'd give us a preview of how many projects actually depend on this behavior. Re making an official std.optional, I didn't believe that was an option that would be acceptable, due to the significant feature overlap with Nullable. I'm not even sure if Nullable should be deprecated in that case, it does have a distinct niche for "types that are not expected to be null when accessed", such as late initialized values. |
Some libraries rely on However, I don't see why you label it as a breaking change. It's a deprecation. The whole point of |
Re "Some libraries rely on I've labeled this as "breaking" because a deprecation entails an intent to remove. The actual removal, which would be the actual "breaking change", should only be a formality. |
Even if nothing breaks on buildkite, I'd still be very wary of changing the behaviour of a standard library type. |
Fair enough. I'll look into writing up a edit: Though didn't we just have W&A saying, at dconf, with the full backing of the community, that we should be more willing to make breaking changes in the interest of improvement? |
My comment was an answer to @atilaneves . Writing a new
So all deprecations are breaking changes ? I think we use a different vocabulary here.
Isn't that the point of a deprecation though, that we don't just "change behavior" ? |
For the purpose of a pull request, yes. The actual removal should be a near-automatic action. Accepting a deprecating PR entails accepting an obligation to remove. |
That doesn't make any sense. A deprecation doesn't cause any other component to fail. The removal does. A good example of a breaking change is a function / type starting to behave differently. This is not the case here. |
To me, the question isn't "what will this commit in itself do" but "what will merging this commit, commit the maintainers to do." It's the PR title, not the commit title. In any case, given that it says "deprecate" in the title, I think it's clear enough. |
Phobos v2 will come. This vision is there, so why not move the new Optional type in std.v2? The module isn't there yet, but it would be a great opportunity to get started on the v2 story. |
I don't see |
@WalterBright Hi, before I start writing up a PR, do you think edit: nevermind I just did it #7065 |
The implicit cast is just error prone and should be looked at as a bug in Nullable. Languages should probably fix gaping holes even if they're in standard types and causes down stream work. The code is already broken downstream because they're using nullable as is. |
Though it may be argued that 90% of the places that currently use |
9afa647
to
d2ef9f8
Compare
Did we check how many projects would be affected on Buildkite (i.e. add a temporary test commit to check that). |
Would it be possible to no go with the deprecation route on this one and just remove it. This is really really bad right now. This actually crashes:
You cannot, at this time, use any logging functions in vibe-d for example because of this if you have a struct with a null Nullable in it. |
And just to frame this a bit better. At work I've managed to get D in use a bit. I got another part of the project to start using D as well ... and of course they hit this bug, and if you can't log objects in a web framework, well... they switched to rust 😢 |
No disagreement here.
No. Some people use it the right way and it's not right (nor a sustainable policy) to break their code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to a comply with the deprecation DIP
d2ef9f8
to
0e24007
Compare
Should now comply with DIP1013. Removal is set for >2.096. |
Using it implicitly without a Furthermore, consider how serious this bug really is: it literally triggers an assert from within the standard library, after which, your program is invalid - literally by definition. And in release mode this assert will not be hit. This triggers it: https://github.com/dlang/phobos/blob/master/std/format.d#L3448 |
It's not about being "the right thing to do". Take this pull request as an example. The code is correct, as it only uses the implicit conversion after an So why would you forgo the deprecation ? |
That's the whole point of deprecation. We deprecate a symbol that we think is more harmful to keep around than to leave as-is. The change doesn't break anything. And then after the deprecation period (which is 10 full releases by default, making it roughly two years), we remove the symbol, and then anyone who didn't change their code during the deprecation period ends up with broken code. So, if we're going to make a change like this, deprecation like this PR is using is exactly the right thing to do. So, the question is whether the current behavior is worse than requiring that any code using
Absolutely not. If a change is not a bug fix, then it must go through the deprecation period, otherwise we're breaking existing code that works perfectly fine. This change is being proposed on the basis that having the Also, if/once this PR is merged and released, then any new code which uses
The assertion in Simply removing the |
Honestly, that sounds like a bug in Either way, a workaround to that problem should be to simply add a |
@Geod24 fair enough. The problem is that the code I posted doesn't use the implicit cast. I guess we'll just have to "fix" where/when it pops up in phobos over the next 2 years apparently, if someone notices it and reports it. @jmdavis pieces of code can have design bugs as well. This one is clear as day. And it will fix any piece of generic code based on Maybe |
@wilzbach https://buildkite.com/dlang/phobos/builds/1697 now shows a more friendly picture. Several high-profile projects would be broken, but it mostly seems to be the same |
ping? |
ping |
This PR deprecates
alias get this
in Nullable.Nullable effectively creates a "pointer type" out of a regular type, with the addition of a null state that throws an error when trying to access the contained value of an empty
Nullable
withNullable.get
.However, this conversion may happen implicitly.
Effect
In the short term, all code that takes advantage of the implicit conversion of
Nullable!T
toT
will print a deprecation warning, or fail with-de
. Needless to say this is a breaking change.Motivation
For better or worse,
Nullable
has become the de-facto type for making a value optional.However, it also includes functionality to implicitly call its getter, throwing an error on failure. It is thus to my knowledge the only implicit conversion in the language that can error at runtime.
This is like if
int*
implicitly converted toint
by dereferencing. The typesystem is supposed to protect us from things like this, by reminding us to check values for validity before attempting to dereference, decode or otherwise process them. In essence,Nullable
'salias get this
independently reinvents the null pointer crash, then allows it to occur implicitly.Making object references nullable by default has been one of D's decisions that has received the most criticism over the years.
Nullable
does the same, then adds the further problem of implicit conversion to types that aren't usually associated with null pointer crashes. If null pointers are bad,Nullable
recreates them in a worse form.Any existing code that takes advantage of the implicit conversion can be trivially updated by adding a
.get
, if intentional, or an.isNull
check followed by a.get
, if unintentional.Does this really matter?
We have literally spent days of debugging effort to this
bugfeature.Do you really expect this to get merged as-is?
Any previous attempt to spark a debate about this topic has run into broad disinterest. The point of this PR is to "put up code", so to speak; to make the cost of deprecating
alias get this
as small as clicking a "merge" button. Hopefully, if people really disagree with this change (which I've also not seen!), they'll take this opportunity to speak up, here or in the forum thread.edit: added a changelog entry
edit: made title less offensively loud