-
-
Notifications
You must be signed in to change notification settings - Fork 741
Fix for issue# 8362. #675
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 for issue# 8362. #675
Conversation
The changes look reasonable to me. |
static assert( isSafe!(mul)); | ||
static assert(!isSafe!add); | ||
static assert( isSafe!sub); | ||
static assert( isSafe!mul); | ||
-------------------- | ||
*/ | ||
template isSafe(alias func) |
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.
Not a fan of the fact that we have @safe and @trusted but isSafe is a disjunction of them (instead of isSafe meaning safe and isTrusted meaning trusted). Could we change things such that we have isSafe, isTrusted, and isSafelyCallable? The latter would implement the functionality of the currently proposed isSafe.
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.
I'd argue against it based on the fact that it could break code except for the fact that isSafe
is pretty much completely broken right now anyway, and I tend to agree with your dislike for isSafe
evaluating to true
for @trusted
as well. So, I'll make the changes.
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.
On the downside, the whole naming scheme was built around the idea that isSafe
would be true
for @trusted
: isSafe
, isUnsafe
, areAllSafe
, and for the most part, you only care whether something is @system
or not... So, I don't know. Having isX
and areAllX
for all of them seems a bit much. Maybe I can up with a good templatization scheme using enums or something. I'll have to think about this.
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.
Actually, I'm not so sure if we should change this in the first place. There is no valid reason whatsoever for a caller to check if a function is @safe
or @trusted
. Introducing this primitives just makes it easier for users to write wrong code.
Additionally, if @trusted
goes away in the future – I hope it is changed to just annotate the function @safe
and mark all of its body @trusted
–, having those two templates, which would probably be changed to mean the same thing, would be confusing.
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.
Also, not introducing isSafe
and isTrusted
would provide a clean migration path to the fixed implementation and naming: Just schedule the isSafe
and areAllSafe
for deprecation, while adding isSafelyCallable
as a replacement.
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.
Your change doesn't just fix isSafe
, it changes its semantics (as requested by Andrei, but that doesn't make it less of a breaking change). This is why I think we should be clear about what we are doing…
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.
Your change doesn't just fix isSafe, it changes its semantics
I never said otherwise.
This is why I think we should be clear what we are doing…
I don't see changing isSafe
as being a problem even with your proposal, since it would just end up doing what it does now anyway, since @trusted
would be identical from the perspective of the function signature. The problem is that it introduces isSafelyCallable
, which currently is better to use than isSafe
due to how @safe
and @trusted
work but which becomes completely pointless if we go with your proposal. So, we'd end up adding a function, essentially telling you to use it instead of isSafe
, then turn around to deprecate it and tell you to use isSafe
again, because @trusted
will now mean @safe
as far as function signatures are concerned. That's the only real problem that I see here. But if we don't end up going with your proposal, then these changes are exactly what we want.
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.
The @trusted
debate is one thing, but what I'm worried about here is that this a breaking change to isSafe
for non-functions, for questionable benefits. We have recently been very careful about the way to handle breaking changes. Yes, isSafelyCallable
is currently the right choice for virtually all applications. But there is probably code out there which uses isSafe
…
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.
What do you mean a breaking change for isSafe
for non-functions? And any code which uses isSafe
is inherently broken anyway, since isSafe
has never worked.
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.
Okay, seems like I underestimated how broken isSafe
currently is (or, well, was), but this compiles, and won't with the changes folded in:
import std.traits;
alias void function() @safe SafeFn;
static assert(isSafe!(SafeFn.init));
alias void function() @trusted TrustedFn;
static assert(isSafe!(TrustedFn.init));
alias void delegate() @safe SafeDg;
static assert(isSafe!(SafeDg.init));
alias void delegate() @trusted TrustedDg;
static assert(isSafe!(TrustedDg.init));
I just grepped through my sources, and apparently I have actually written code which uses isSafe
in template constraints (and RefRange
seems to use it as well, btw) – I must have been incredibly lucky, because I can't recall noticing any problems with it. Yes, my code probably works out of coincidence given the bugs in the isSafe
implementation, but it is supposed to work given the Phobos docs.
Changing the two instance of isSafe
to isSafelyCallable
would be trivial, of course, but I'm not sure if it's worth introducing a breaking change, given that – and this is where the argument detailed in the forum thread comes in, regardless of whether the proposal is accepted or not – it doesn't really make sense to use isSafe
and isTrusted
in just about any situation. And if somebody really needs that information, they can always use FunctionAttributes
directly.
By the way, SetFunctionAttributes
actually distinguishes between @safe
and @trusted
for consistency, but this, i.e. pretty printing function types, is about the only use case for isSafe
/isTrusted
I can think of. And if you are doing that, chances are you are using all of the other FunctionAttribute
s anyway.
waiting |
FWIW isSafelyCallable could be a possibility. |
Okay. Updated. It has |
|
Ah. Good point. Will fix. |
Okay. |
If we want to remove Besides, I can't imagine that much external code uses it in its broken state. And it isn't used in Phobos anymore either – originally, it was included as part of the |
My concern was removing it in the middle of a beta, and this pull request may get pulled in as part of that in order to fix bug# 8450. However, what we can do cleanly is change it back to really being the same as |
Okay. |
Hm, I'm still not sure if this is the most consistent solution, but I see your point. If we go with this, I'd explicitly state that the template never worked as advertised, to avoid »why on earth was it necessary to deprecate my perfectly good function«-type responses in the future. |
"std.traits.isSafe doesn't work with unsafe lamdba functions"
@klickverbot I tend to see isSafe and isTrusted more like reflection primitives than things a caller would be interested in. They do the obvious thing of looking at the respective flags. I'll pull this in now. |
@andralex: We already have Also, as I noted in the forum discussion, there is no semantic reason to look at which of both attributes a function bears. They are completely equivalent. Where would you use |
Since the regression count is falling quickly: Ping? Are we going to leave this in the current state? To summarize, why I think merging the changes was not a good decision, but a mistake in the heat of trying to get a release out: The change breaks code. The following snipped always compiled, and was supposed to according to the documentation. import std.traits;
void safe() @safe;
void trusted() @trusted;
void system() @system;
struct Test
{
void safe() @safe;
void trusted() @trusted;
void system() @system;
}
static assert(isSafe!(safe));
static assert(isSafe!(trusted));
static assert(!isSafe!(system));
Test t;
static assert(isSafe!(t.safe));
static assert(isSafe!(t.trusted));
static assert(!isSafe!(t.system));
Yes, ——— [1] Besides pretty-printing a function type, as done e.g. in the |
I would expect all actual code breakage to be caused by What would you be using The only problem that I see with these changes is that if |
No, the breakage is caused by arbitrarily changing the definition of
This is exactly what I am using it for and what I would expect other people to use it for. How is this an argument for changing |
If that's what you're doing, I don't see how it breaks anything. It just makes it so that your functions get marked as |
And as for a deprecation cycle, how would you do that? We could introduce |
Huh? The function in question couldn't be called by The second use case where I'm using |
And there is no reason for doing so. I'm still waiting for arguments why we should have
Sigh. You are right, code using But the code isn't broken. It used I don't see how the current implementation being buggy is an excuse to screw all its users. For me as a Phobos user, this is just like if we discovered that using |
@klickverbot Is this a huge deal? If not, let's just move on. The simple argument is, there's |
@andralex: My definition of »let's just move on« is to revert the change, in the sense of just changing I really don't want to waste any more time on this, but the change breaks (my) code, and I don't see how this should be a good idea. Yes, the name |
I think my underlying assumption here is that fewer people use |
If we're going to change it, I think that we should just change it now. Otherwise, we just leave I'm surprised that anyone would have written code which required that something be |
I also explained why this breaking change doesn't gain us anything. If you are unhappy with the name, why don't we just add Although I think it's somewhat unnecessary, I won't complain about that, name changes in Phobos do happen, and it's not worth the time bikeshedding about that. |
The deprecation path works fine for renaming, replacing, or removing functions/templates, but it doesn't really work very well for changing what a function/template is doing. |
@jmdavis: Why should we want to change it in the first place? You've successfully been avoiding to answer that question for the whole discussion, even though I provided two arguments why we shouldn't. |
Because the name is completely wrong. It effectively lies about what the template is doing. |
@jmdavis: This might be a reason to change the name, but not to add a new, completely unnecessary |
I don't see any problem with having The only real issue that I have here is the fact that if |
Sorry, this is just plain wrong. Having useless cruft in an API is always something you want to avoid.
Okay, so let me get this straight. The question is whether to add two templates,
Now, tell me, what is so crucial about having |
I'm going to go with klickverbot on this, we shouldn't be redesigning things in the beta. Also, there's David Nadlinger's thread "@trusted considered harmful" which brings up some solid points, and we should take those into account in any design change. We also need to stop breaking existing code. Names in the library with breaking behavior should get different names. |
@WalterBright: I am David Nadlinger. ;) Unfortunately my GitHub account had existed under this nick rather than my real name long before D was on GitHub, so I couldn't easily change it to make the connection more obvious, without breaking people's repo clones. |
Sorry, I get lost as to which nick goes with which name! May I suggest then changing your avatar image to be "David Nadlinger" rather than "k"? That would solve both problems. |
BTW, in the service of enhancing one's professional reputation, it is a good idea to post professional work under one's real name. It puts one's reputation under one's own control, rather than someone else writing about one and that bubbling to the top of google's results. Save the pseudonyms for the political forums :-) |
It's also a good career move to stake out: www.yourname.com at least so nobody else grabs it. |
LOL. My names so common that that sort of thing would be pointless (though I don't expect that David would have that problem - he' the only person I've ever heard of with the last name Nadlinger). I do use my real name for all of the programming and programming-related stuff I do online though, for whatever it's worth. I'll have a pull request reverting the non-fix related part of this pull request shortly. |
OK, will undo this. What's a robust method? I'm looking at Guess we should have a script for that! |
@andralex There's a required bugfix as part of the changes. We don't want to revert them. I'll be creating a pull request which undoes the unwanted changes shortly. |
OK since @jmdavis is doing the work I'm off the hook. Nevertheless I'm curious about how the pull excision could be done. |
You use git-revert to create a pull request which is the reverse of the one you want to revert. But it reverts an entire pull request (or multiple) at once, not pieces. |
@andralex: If you wanted to revert the whole commit – which, in this case, you most likely don't, since If you just want to undo a commit locally, before making it public, I'd suggest using e.g. |
Thanks folks. This is the darndest thing - googling for "github undo pull" doesn't yield git-revert on the first page... |
@WalterBright: Thanks for the suggestions – I already grabbed the names quite a while ago, and almost exclusively participate in open source projects under my real name right now. GitHub is somewhat different, though, until not too long ago it has been the norm to use pseudonyms here (with the real name listed in the profile, of course) – if you look at the GitHub team or the Rails committer list, you'll find a lot of odd nicknames. Also, sorry everyone for the overly long discussion. I just thought it wouldn't be a good idea to introduce breaking changes by adding new templates in the middle of a beta, regardless of how the |
"std.traits.isSafe doesn't work with unsafe lamdba functions"
std.traits.isSafe
seems to have been fairly broken. It's first branch was done completely incorrectly and showed a lack of understanding of howFunctionAttribute
works, and the second half didn't take into account that the function wouldn't compile if the argument was@system
. Templatizing the function that it used to test would have fixed it, but I just fixed the first part so that it should work for everything.The original problem was that something like
didn't compile, since the latter half of
isSafe
didn't work with@system
at all.