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

[std.range.chain] Use static assert instead of complex constraint #8821

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

ntrel
Copy link
Contributor

@ntrel ntrel commented Sep 22, 2023

We can give more precise errors then. chain is actually mentioned in this paper (thanks @ibuclaw):
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2429r0.pdf

chain(Ranges...)(Ranges rs)
with Ranges = (int[], int)
must satisfy the following constraint:
allSatisfy!(isInputRange, staticMap!(Unqual, Ranges))
This error narrowed down which constraint in the conjunction failed (i.e. it wasn't the length check or the
common type check), but it didn't tell us which argument failed the constraint, and it didn't tell us why, or
what we can do about it.

Now we get:

test.d(10): Error: static assert:  `int` is not an input range
test.d(792):        instantiated from here: `chain!(int, int[])`

I've included a constraint that at least one argument is an input range. This is to reduce the chance of breaking code that uses an overload of chain defined elsewhere.

We can give more precise errors then.

I've included a constraint that at least one argument is an input range.
This is to reduce the chance of breaking code that uses an overload of
chain defined elsewhere.
@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @ntrel! 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 coverage diff by visiting the details link of the codecov check)
  • 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

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.

Testing this PR locally

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

dub run digger -- build "master + phobos#8821"

@@ -928,9 +928,17 @@ See_Also: $(LREF only) to chain values to a range
*/
auto chain(Ranges...)(Ranges rs)
if (Ranges.length > 0 &&
allSatisfy!(isInputRange, staticMap!(Unqual, Ranges)) &&
!is(CommonType!(staticMap!(ElementType, staticMap!(Unqual, Ranges))) == void))
anySatisfy!(isInputRange, staticMap!(Unqual, Ranges)))
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason to have this anySatisfy constraint here but not on chooseAmong?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added this constraint to chooseAmong now for consistency. The only reason was I thought that was a less likely name to have a collision (see my next comment).

@PetarKirov
Copy link
Member

@nrtel Keep in mind that there are downsides to converting template constraints to static asserts, see: #8745 (review)

I'm saying that this specific PR is problematic (I haven't had the chance to review it), but I'm mentioning this for your information.

@ntrel
Copy link
Contributor Author

ntrel commented Nov 6, 2023

@PetarKirov I am trying to avoid breaking anyone's code unnecessarily, which is why e.g. I made chain require at least one input range, in case there are functions called chain in other imported modules.

The other point is that removing constraints means the generic type requirements are undocumented. One solution to this would be to make in contract blocks appear in the documentation and put the static assert code inside one. Perhaps the documentation could show them collapsed by default, or collapsible at least, to save space.

@pbackus
Copy link
Contributor

pbackus commented Nov 6, 2023

@PetarKirov It seems to me like the kind code that broke in the linked PR—where a user relies on overload resolution to choose between a Phobos function and their own version of the same symbol—could just as easily have been broken by merely adding a new overload of equal, without touching the existing one.

Unless we want to adopt a blanket policy of never adding new overloads to existing Phobos functions (do we?), I think we must conclude that we do not, in general, guarantee backward compatibility for this kind of usage.

Now, maybe equal is particularly high-risk in this regard, so it's worth blocking changes to it while still allowing them elsewhere. But is the same true for chain, choose, and chooseAmong? I don't have a good answer here; it's hard to decide where to draw the line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants