-
-
Notifications
You must be signed in to change notification settings - Fork 700
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 22414 - clamp(a, b, c) should always return typeof(a) #8293
Conversation
Thanks for your pull request, @andralex! Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + phobos#8293" |
auto clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper) | ||
if (is(typeof(max(min(val, upper), lower)))) | ||
T1 clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper) | ||
if (is(typeof(val.lessThan(lower) ? lower : val.greaterThan(upper) ? upper : val) : T1)) |
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.
That doesn't seem right. E.g., I think it should be/previously was possible to clamp an int
with lower
and upper
of type long
.
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.
Good point, I'll think of how to get that done.
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.
It's interesting there were no unittests for such a case. Upon further thinking, I think such calls should be disallowed during compilation (if we agree that the return of clamp should be the same type as that of the clamped value). Consider:
int fun(int x)
{
x = clamp(x, long.max, long.max);
....
}
This can't possibly work. x
is always less than the left clamp, and furthermore the left clamp value cannot be represented as an int
.
We could use assert
or exceptions to weed out these cases, but the whole thing starts to smell of hiding bugs on the call site. Better disable the call entirely and compel the user to use appropriate types within the call.
I'll leave the code as is pending other arguments.
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 is the outcome of clamping an int
with uint
values that int
cannot represent?
int x = ...;
x = clamp(x, uint.max, uint.max);
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.
@JohanEngelen thanks for raising the point. Per this PR is returns uint.max
cast to int
, i.e. -1.
This is in keeping with ordinary conversion rules, i.e. uint.max
is entirely representable as an int
and the representation's value is -1.
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.
@JohanEngelen I added a unittest for that case.
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.
Can you abstract it a little and document that behavior? (I think the behavior is that the comparisons are done "correctly", and that the outcome/clamped value is converted to the return type using standard integer conversion rules?)
merged without documentation improvement, nor author response to the comment... |
@JohanEngelen Oh, I'm sorry, I didn't properly inspect the date of your comment and the date of the last commit. Browsing through the PR page it seemed like a commit was made after your last comment. And the documentation does specify that "Comparisons are made correctly (using However, I take it that you want the "using the standard integer conversion rules" added? |
yeah. At least I did not know what |
(this is a downside of the way PRs are merged. What works better, I think, is accepting a PR with a 'lgtm' and then the author commits the PR himself, where he can make last minute small changes. Or you can accept a PR with some nits, author fixes nits and merges PR... oh well :)) |
Sigh.