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

Adding the has_item function to the iterator trait. #127604

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

Conversation

yonikremer
Copy link

Refrences

the tracking issue and the feature proposal.

Here is my implementation, including the doc string and tests

@rustbot
Copy link
Collaborator

rustbot commented Jul 11, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @Amanieu (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 11, 2024
@rustbot
Copy link
Collaborator

rustbot commented Jul 11, 2024

rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead.

cc @rust-lang/rust-analyzer

@rust-log-analyzer

This comment has been minimized.

Comment on lines +6077 to +6087
"##,
},
Lint {
label: "contains",
description: r##"# `contains`

The tracking issue for this feature is: [#94047]

[#94047]: https://github.com/rust-lang/rust/issues/94047


Copy link
Member

Choose a reason for hiding this comment

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

This file is autogenerated so no need for adding this (its also adding it one slot too late)

Copy link
Contributor

Choose a reason for hiding this comment

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

@yonikremer see this comment too, you can revert this file

Comment on lines 39 to 40
# Adds a function to check if an element is contained in an iterator
contains = []
Copy link
Contributor

@tgross35 tgross35 Jul 11, 2024

Choose a reason for hiding this comment

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

Library features don't need to be listed here, this is just for Cargo features that get exposed during build-std

Comment on lines 81 to 85

/// Advances the iterator and returns an array containing the next `N` values.
/// Advances the iterator and returns an array has_iteming the next `N` values.
///
/// If there are not enough elements to fill the array then `Err` is returned
/// containing an iterator over the remaining elements.
/// has_iteming an iterator over the remaining elements.
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like maybe you did find+replace on contain? Change looks accidental (more of these below, please double check the diff)

Comment on lines 1329 to 1330
/// The returned iterator is a prefix of length `n` if the original iterator
/// contains at least `n` elements, otherwise it contains all of the
/// has_items at least `n` elements, otherwise it has_items all of the
Copy link
Contributor

Choose a reason for hiding this comment

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

Same

Comment on lines 3358 to 3359

/// Converts an iterator of pairs into a pair of containers.
/// Converts an iterator of pairs into a pair of has_itemers.
Copy link
Contributor

Choose a reason for hiding this comment

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

Lol, this one is kind of funny

Comment on lines 4072 to 4092
/// Example:
/// ```
/// #![feature(iter_has_item)]
/// assert!(![1i32, 2i32, 3i32].iter().has_item(&4i32));
/// assert!([Some(2i32), Option::<i32>::None].iter().has_item(&None));
/// assert!([Some(2i32), Option::<i32>::None].iter().has_item(&Some(2i32)));
/// assert!(!Vec::<i32>::new().iter().has_item(&1i32));
/// assert!([1i32, 2i32, 2i32, 3i32].iter().has_item(&2i32));
/// #[derive(PartialEq)]
/// struct Item {
/// value: i32,
/// }
/// assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().has_item(&Item { value: 2i32 }));
/// assert!(["a", "b", "c"].iter().has_item(&"b".to_owned()));
/// assert!(!["a", "b", "c"].iter().has_item(&"d".to_owned()));
/// assert!(["a", "b", "c"].iter().has_item(&"b"));
/// assert!(!["a", "b", "c"].iter().has_item(&"d"));
/// assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().has_item(&"b"));
/// assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().has_item(&"d"));
/// assert!((1..1000).has_item(500i32));
/// ```
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned at the ACP, make the doc example something small and easy to understand. More complete testing only needs to live in unit/integration tests.

Comment on lines 4064 to 4066
/// Checks if the Iterator has a value.
/// 'has_items' is short-circuiting; in other words, it will stop processing
/// as soon as the function finds the item in the Iterator.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Checks if the Iterator has a value.
/// 'has_items' is short-circuiting; in other words, it will stop processing
/// as soon as the function finds the item in the Iterator.
/// Returns `true` if the iterator contains a value.
///
/// 'has_items' is short-circuiting; in other words, it will stop processing
/// as soon as the function finds the item in the `Iterator`.

Made the summary line more consistent with slice::contains/HashSet::contains. Also remember that a line break is needed between the summary and the content (otherwise the whole thing gets treated as a summary line).

Comment on lines 4094 to 4095
#[unstable(feature = "iter_has_item", reason = "new API", issue = "127494")]
fn has_item<Q: ?Sized>(&mut self, item: Q) -> bool
Copy link
Contributor

@tgross35 tgross35 Jul 11, 2024

Choose a reason for hiding this comment

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

From #127494, this can be renamed back to contains

@rust-log-analyzer

This comment has been minimized.

@yonikremer
Copy link
Author

@tgross35 I have updated the pull request. Now it breaks external libraries like ide-assist.
It should be fixed by Supertrait item shadowing. Is there a way to activate both features and see if everything works as intended?

@yonikremer
Copy link
Author

There is a pull request for Super trait shadowing here. It just needs someone to review it.

@@ -1327,7 +1327,7 @@ pub trait Iterator {
/// `take(n)` yields elements until `n` elements are yielded or the end of
/// the iterator is reached (whichever happens first).
/// The returned iterator is a prefix of length `n` if the original iterator
/// contains at least `n` elements, otherwise it contains all of the
/// contains at least `n` elements, otherwise it containss all of the
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// contains at least `n` elements, otherwise it containss all of the
/// contains at least `n` elements, otherwise it contains all of the

library/core/src/iter/traits/iterator.rs Outdated Show resolved Hide resolved
Co-authored-by: Juniper Tyree <[email protected]>
@rust-log-analyzer

This comment has been minimized.

Comment on lines +6077 to +6087
"##,
},
Lint {
label: "contains",
description: r##"# `contains`

The tracking issue for this feature is: [#94047]

[#94047]: https://github.com/rust-lang/rust/issues/94047


Copy link
Contributor

Choose a reason for hiding this comment

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

@yonikremer see this comment too, you can revert this file

Comment on lines +4069 to +4071
/// Performance:
/// This method checks the whole iterator, which takes O(n) time.
/// If the iterator is sorted, or a hash map please use the appropriate method instead.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// Performance:
/// This method checks the whole iterator, which takes O(n) time.
/// If the iterator is sorted, or a hash map please use the appropriate method instead.
/// This method checks the whole iterator, which is O(n). If the iterator is a sorted
/// slice, [`binary_search`](slice::binary_search) may be faster. If this is an iterator
/// on collections that have a `.contains()` or `.contains_key()` method (such as
/// [`HashMap`] or [`BTreeSet`]), using those methods directly will be faster.

We can be more specific about what the appropriate methods are here. No section heading needed, I think rustdoc would have just merged Performance: into the next paragraph anyway.

You can check the rendering with ./x doc library/core --open

Comment on lines +619 to +653
#[test]
fn test_happy_path_item_not_in_iterator() {
assert!(![1i32, 2i32, 3i32].iter().contains(&4i32));
}

#[test]
fn test_edge_case_handling_none_values() {
assert!([Some(2i32), Option::<i32>::None].iter().contains(&None));
assert!([Some(2i32), Option::<i32>::None].iter().contains(&Some(2i32)));
}

#[test]
fn test_edge_case_handling_empty_iterator() {
assert!(!Vec::<i32>::new().iter().contains(&1i32));
}

#[test]
fn test_edge_case_handling_iterator_with_duplicates() {
assert!([1i32, 2i32, 2i32, 3i32].iter().contains(&2i32));
}

#[test]
/// Tests that short-circuiting works correctly when using `contains`
/// When you run the function, it should move the iterator forward after the first appearance of the item
fn test_short_circuiting() {
let vector: Vec<i32> = vec![1i32, 2i32, 3i32, 1i32, 1i32];
let mut iterator = vector.into_iter();
assert!(iterator.contains(1i32));
assert_eq!(iterator.next(), Some(2));
assert!(!iterator.contains(4i32));
assert_eq!(iterator.next(), None);
}

#[test]
fn test_edge_case_handling_iterator_with_custom_struct() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: since these tests only check .contains(), they should have test_contains in the name

Comment on lines 4076 to 4081
/// assert!([1, 2, 3].iter().contains(&1));
/// assert!(![1, 2, 3].iter().contains(&4));
/// // You can check if a String is in a string slice iterator.
/// assert!(["a", "b", "c"].iter().contains(&"b".to_owned()));
/// // You can also check if a String iterator contains a string slice.
/// assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"b"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe make it an example that you couldn't just use slice::contains(...) on, like [1, 2, 3].iter().map(|x| x * 3).contains(6)

Comment on lines 1 to 6
fn main() {
let vec = Vec::new();
Vec::contains(&vec, &0);
//~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
//~^ ERROR `Vec<_, _>` is not an iterator [E0599]
//~| HELP the function `contains` is implemented on `[_]`
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Bit of an unfortunate suggestion change for an unstable method. This was added in #100302, cc @compiler-errors since this will no longer test what it was intended to.

Copy link
Member

Choose a reason for hiding this comment

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

pls file a bug, we probably can filter by stability or sth idk

@compiler-errors
Copy link
Member

also please make sure this commit history gets squashed before approval -- 27 commits is a bit excessive, especially when a lot of the commits are removing/renaming and don't add much valuable information to the commit history lol

@tgross35
Copy link
Contributor

@tgross35 I have updated the pull request. Now it breaks external libraries like ide-assist. It should be fixed by Supertrait item shadowing. Is there a way to activate both features and see if everything works as intended?

That PR is a draft so it is not ready yet. That feature will fix the conflicts with itertools on stable features, there shouldn't be any conflict for unstable features. But it will raise the unstable_name_collisions, as seen in the RA build failures (you can fix these either by using the suggested fully qualified syntax, or with #[allow(unstable_name_collisions)]).

You can try it locally to see the interactions. After you build you can do rustup toolchain link stage1 ... (see https://rustc-dev-guide.rust-lang.org/building/quickstart.html), and then cargo +stage1 ... in a test crate to use it.

@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 12, 2024
@rustbot
Copy link
Collaborator

rustbot commented Jul 12, 2024

There are merge commits (commits with multiple parents) in your changes. We have a no merge policy so these commits will need to be removed for this pull request to be merged.

You can start a rebase with the following commands:

$ # rebase
$ git pull --rebase https://github.com/rust-lang/rust.git master
$ git push --force-with-lease

The following commits are merge commits:

@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#12 [ 5/11] RUN npm install [email protected] [email protected] -g
#12 5.037 npm WARN deprecated [email protected]: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
#12 5.103 npm WARN deprecated [email protected]: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
#12 5.106 npm WARN deprecated [email protected]: Rimraf versions prior to v4 are no longer supported
#12 5.166 npm WARN deprecated @humanwhocodes/[email protected]: Use @eslint/config-array instead
#12 5.190 npm WARN deprecated [email protected]: Glob versions prior to v9 are no longer supported
#12 5.207 npm WARN deprecated @humanwhocodes/[email protected]: Use @eslint/object-schema instead
#12 6.367 
#12 6.367 added 205 packages in 6s
#12 6.367 
#12 6.368 20 packages are looking for funding
---
#16 3.568 Building wheels for collected packages: reuse
#16 3.569   Building wheel for reuse (pyproject.toml): started
#16 3.915   Building wheel for reuse (pyproject.toml): finished with status 'done'
#16 3.916   Created wheel for reuse: filename=reuse-1.1.0-cp310-cp310-manylinux_2_35_x86_64.whl size=181117 sha256=f5f58750481f69515c2c0d1d503daf565e2565c370d07fc6aeb95fe3498b4269
#16 3.916   Stored in directory: /tmp/pip-ephem-wheel-cache-fnplqin3/wheels/c2/3c/b9/1120c2ab4bd82694f7e6f0537dc5b9a085c13e2c69a8d0c76d
#16 3.919 Installing collected packages: boolean-py, binaryornot, setuptools, reuse, python-debian, markupsafe, license-expression, jinja2, chardet
#16 3.942   Attempting uninstall: setuptools
#16 3.942     Found existing installation: setuptools 59.6.0
#16 3.943     Not uninstalling setuptools at /usr/lib/python3/dist-packages, outside environment /usr
---
    Checking ide-assists v0.0.0 (/checkout/src/tools/rust-analyzer/crates/ide-assists)
error: a method with this name may be added to the standard library in the future
   --> crates/ide-assists/src/handlers/bool_to_enum.rs:372:48
    |
372 |     if !bin_expr.lhs()?.syntax().descendants().contains(name.syntax()) {
    |
    = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
    = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
    = help: call with fully qualified syntax `itertools::Itertools::contains(...)` to keep using the current method
    = help: call with fully qualified syntax `itertools::Itertools::contains(...)` to keep using the current method
    = note: `-D unstable-name-collisions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(unstable_name_collisions)]`
help: add `#![feature(iter_contains)]` to the crate attributes to enable `std::iter::Iterator::contains`
   --> crates/ide-assists/src/lib.rs:63:1
    |
63  + #![feature(iter_contains)]

error: a method with this name may be added to the standard library in the future
   --> crates/ide-assists/src/handlers/bool_to_enum.rs:438:41
    |
    |
438 |     if !receiver.syntax().descendants().contains(name.syntax()) {
    |
    = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
    = note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
    = help: call with fully qualified syntax `itertools::Itertools::contains(...)` to keep using the current method
    = help: call with fully qualified syntax `itertools::Itertools::contains(...)` to keep using the current method
help: add `#![feature(iter_contains)]` to the crate attributes to enable `std::iter::Iterator::contains`
   --> crates/ide-assists/src/lib.rs:63:1
    |
63  + #![feature(iter_contains)]

    Checking ide-diagnostics v0.0.0 (/checkout/src/tools/rust-analyzer/crates/ide-diagnostics)
    Checking load-cargo v0.0.0 (/checkout/src/tools/rust-analyzer/crates/load-cargo)
error: could not compile `ide-assists` (lib) due to 2 previous errors

@bors
Copy link
Contributor

bors commented Jul 28, 2024

☔ The latest upstream changes (presumably #128313) made this pull request unmergeable. Please resolve the merge conflicts.

@Dylan-DPC
Copy link
Member

@yonikremer this still has a merge confict that needs to be removed and pr rebased over in order for this to proceed. If you need help doing this let us know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants