From c068fdc96f7923509f5d56f88df494b698ee94ce Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Tue, 9 Jul 2024 00:19:24 +0300 Subject: [PATCH 01/28] implemented the contains feature --- library/core/src/iter/traits/iterator.rs | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 733d414d44465..2923fe34a4616 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4060,6 +4060,34 @@ pub trait Iterator { { unreachable!("Always specialized"); } + + + /// Checks if the Iterator contains the value. + /// 'contains' is short-circuiting; in other words, it will stop processing + /// as soon as the closure returns `true`. + /// + /// 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. + /// + /// Example: + /// ``` + /// #![feature(contains)] + /// assert!([1, 2, 3].iter().contain(1)); + /// assert!(![1, 2, 3].iter().contain(4)); + /// assert!([Some(2), None].iter().contain(None)); + /// assert!([Some(2), None].iter().contain(Some(2))); + /// ``` + #[unstable(feature="contains", reason = "new API", issue = "127494")] + fn contain(&mut self, item: Self::Item) -> bool + where Self::Item: Eq{ + for element in self{ + if element == item{ + return true; + } + } + return false; + } } /// Compares two iterators element-wise using the given function. From c143b425431428a4433c29ef1f71b183163f7f9f Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Tue, 9 Jul 2024 11:25:31 +0300 Subject: [PATCH 02/28] the function contains can now get every type that can be borrowed as Self::Item --- library/core/src/iter/traits/iterator.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 2923fe34a4616..c53257ea10663 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2,6 +2,7 @@ use crate::array; use crate::cmp::{self, Ordering}; use crate::num::NonZero; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; +use crate::borrow::Borrow; use super::super::try_process; use super::super::ByRefSized; @@ -4071,7 +4072,7 @@ pub trait Iterator { /// If the iterator is sorted, or a hash map please use the appropriate method. /// /// Example: - /// ``` + /// ```rust /// #![feature(contains)] /// assert!([1, 2, 3].iter().contain(1)); /// assert!(![1, 2, 3].iter().contain(4)); @@ -4079,10 +4080,15 @@ pub trait Iterator { /// assert!([Some(2), None].iter().contain(Some(2))); /// ``` #[unstable(feature="contains", reason = "new API", issue = "127494")] - fn contain(&mut self, item: Self::Item) -> bool - where Self::Item: Eq{ + fn contain<Q>(&mut self, item: Q) -> bool + where + Self::Item: PartialEq, + Q: Borrow<Self::Item>, + Self: Sized + { + let borrowed_item: &Self::Item = item.borrow(); for element in self{ - if element == item{ + if element == *borrowed_item{ return true; } } From 79319981310fefe88d0a2a5de7ed46dbce60ac87 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Tue, 9 Jul 2024 11:25:49 +0300 Subject: [PATCH 03/28] added tests for contain --- library/core/src/iter/traits/iterator.rs | 47 ++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c53257ea10663..e20d05579d869 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4079,6 +4079,53 @@ pub trait Iterator { /// assert!([Some(2), None].iter().contain(None)); /// assert!([Some(2), None].iter().contain(Some(2))); /// ``` + /// + /// Tests: + /// Happy path 1 - the item is in the iterator + /// ```rust + /// let mut iter = [1, 2, 3].iter(); + /// assert!(iter.contain(1)); + /// ``` + /// Happy path 2 - the item is not in the iterator + /// ```rust + /// let mut iter = [1, 2, 3].iter(); + /// assert!(!iter.contain(20)); + /// ``` + /// Edge case 1 - handling None values + /// ```rust + /// let mut iter = [Some(2), None].iter(); + /// assert!(iter.contain(None)); + /// assert!(iter.contain(Some(2))); + /// ``` + /// Edge case 2 - handling empty iterator + /// ```rust + /// let mut iter: Vec<i32> = vec![]; + /// assert!(!iter.iter().contain(1)); + /// ``` + /// Edge case 3 - handling iterator with duplicates + /// ```rust + /// let mut iter = [1, 2, 2, 3].iter(); + /// assert!(iter.contain(2)); + /// ``` + /// Edge case 4 - handling iterator with different types + /// ```rust + /// let mut iter = [1, 2, "3"].iter(); + /// assert!(iter.contain("3")); + /// ``` + /// Edge case 5 - handling iterator with custom struct + /// ```rust + /// struct Item { + /// value: i32, + /// } + /// let items = [Item { value: 1 }, Item { value: 2 }]; + /// let mut iter = items.iter(); + /// assert!(iter.contain(Item { value: 2 })); + /// ``` + /// Edge case 6 - handling iterator with large number of elements + /// ```rust + /// let mut iter = (1..=1000).iter(); + /// assert!(iter.contain(500)); + /// ``` #[unstable(feature="contains", reason = "new API", issue = "127494")] fn contain<Q>(&mut self, item: Q) -> bool where From fd40ecb44258954e49a38bb2efc9e5aae5dfc3af Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Tue, 9 Jul 2024 11:30:12 +0300 Subject: [PATCH 04/28] formatted the code --- library/core/src/iter/traits/iterator.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index e20d05579d869..8dfbca5bb14cd 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,8 +1,8 @@ use crate::array; +use crate::borrow::Borrow; use crate::cmp::{self, Ordering}; use crate::num::NonZero; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; -use crate::borrow::Borrow; use super::super::try_process; use super::super::ByRefSized; @@ -4062,7 +4062,6 @@ pub trait Iterator { unreachable!("Always specialized"); } - /// Checks if the Iterator contains the value. /// 'contains' is short-circuiting; in other words, it will stop processing /// as soon as the closure returns `true`. @@ -4126,16 +4125,16 @@ pub trait Iterator { /// let mut iter = (1..=1000).iter(); /// assert!(iter.contain(500)); /// ``` - #[unstable(feature="contains", reason = "new API", issue = "127494")] + #[unstable(feature = "contains", reason = "new API", issue = "127494")] fn contain<Q>(&mut self, item: Q) -> bool where Self::Item: PartialEq, Q: Borrow<Self::Item>, - Self: Sized + Self: Sized, { let borrowed_item: &Self::Item = item.borrow(); - for element in self{ - if element == *borrowed_item{ + for element in self { + if element == *borrowed_item { return true; } } From 5372e4b89916887ff12d7011816e58b78b1e9bc2 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Tue, 9 Jul 2024 14:15:19 +0300 Subject: [PATCH 05/28] fixed failing tests --- library/core/src/iter/traits/iterator.rs | 62 ++++++++++++------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 8dfbca5bb14cd..1adcda2a4e7cd 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4071,59 +4071,57 @@ pub trait Iterator { /// If the iterator is sorted, or a hash map please use the appropriate method. /// /// Example: - /// ```rust + /// ``` /// #![feature(contains)] - /// assert!([1, 2, 3].iter().contain(1)); - /// assert!(![1, 2, 3].iter().contain(4)); - /// assert!([Some(2), None].iter().contain(None)); - /// assert!([Some(2), None].iter().contain(Some(2))); + /// assert!([1, 2, 3].iter().contain(&1)); + /// assert!(![1, 2, 3].iter().contain(&4)); + /// assert!([Some(2), None].iter().contain(&None)); + /// assert!([Some(2), None].iter().contain(&Some(2))); /// ``` /// /// Tests: /// Happy path 1 - the item is in the iterator - /// ```rust - /// let mut iter = [1, 2, 3].iter(); - /// assert!(iter.contain(1)); + /// ``` + /// #![feature(contains)] + /// assert!([1, 2, 3].iter().contain(&1)); /// ``` /// Happy path 2 - the item is not in the iterator - /// ```rust - /// let mut iter = [1, 2, 3].iter(); - /// assert!(!iter.contain(20)); + /// ``` + /// #![feature(contains)] + /// assert!(![1, 2, 3].iter().contain(&4)); /// ``` /// Edge case 1 - handling None values - /// ```rust + /// ``` + /// #![feature(contains)] /// let mut iter = [Some(2), None].iter(); - /// assert!(iter.contain(None)); - /// assert!(iter.contain(Some(2))); + /// assert!([Some(2), None].iter().contain(&None)); + /// assert!([Some(2), None].iter().contain(&Some(2))); /// ``` /// Edge case 2 - handling empty iterator - /// ```rust + /// ``` + /// #![feature(contains)] /// let mut iter: Vec<i32> = vec![]; - /// assert!(!iter.iter().contain(1)); + /// assert!(!vec![].iter().contain(&1)); /// ``` /// Edge case 3 - handling iterator with duplicates - /// ```rust + /// ``` + /// #![feature(contains)] /// let mut iter = [1, 2, 2, 3].iter(); - /// assert!(iter.contain(2)); + /// assert!(iter.contain(&2)); /// ``` - /// Edge case 4 - handling iterator with different types - /// ```rust - /// let mut iter = [1, 2, "3"].iter(); - /// assert!(iter.contain("3")); + /// Edge case 4 - handling iterator with custom struct /// ``` - /// Edge case 5 - handling iterator with custom struct - /// ```rust + /// #![feature(contains)] + /// #[derive(PartialEq)] /// struct Item { /// value: i32, /// } - /// let items = [Item { value: 1 }, Item { value: 2 }]; - /// let mut iter = items.iter(); - /// assert!(iter.contain(Item { value: 2 })); - /// ``` - /// Edge case 6 - handling iterator with large number of elements - /// ```rust - /// let mut iter = (1..=1000).iter(); - /// assert!(iter.contain(500)); + /// assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); + /// ``` + /// Edge case 5 - handling iterator with large number of elements + /// ``` + /// #![feature(contains)] + /// assert!((1..1000).contain(&500)); /// ``` #[unstable(feature = "contains", reason = "new API", issue = "127494")] fn contain<Q>(&mut self, item: Q) -> bool From 82d481d64aa9afa63656fe0ef2fe3a0baad693c1 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Wed, 10 Jul 2024 17:50:12 +0300 Subject: [PATCH 06/28] using the feature contains --- library/core/Cargo.toml | 2 ++ library/core/src/lib.rs | 1 + library/core/tests/lib.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index cace4582b489a..8ffa0d831da9a 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -36,6 +36,8 @@ optimize_for_size = [] # Make `RefCell` store additional debugging information, which is printed out when # a borrow error occurs debug_refcell = [] +# Adds a function to check if an element is contained in an iterator +contains = [] [lints.rust.unexpected_cfgs] level = "warn" diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0f82f01e57a71..010d66f7515d6 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -165,6 +165,7 @@ #![feature(const_unicode_case_lookup)] #![feature(const_unsafecell_get_mut)] #![feature(const_waker)] +#![feature(contains)] #![feature(coverage_attribute)] #![feature(duration_consts_float)] #![feature(internal_impls_macro)] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 83a615fcd8be3..72d65f4cc5ebc 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -89,6 +89,7 @@ #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_waker)] +#![feature(contains)] #![feature(never_type)] #![feature(unwrap_infallible)] #![feature(pointer_is_aligned_to)] From 15d6c9f570098f0d6d2d8573f3ea24a77c7e86c8 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Wed, 10 Jul 2024 21:10:34 +0300 Subject: [PATCH 07/28] added the tests for the "contains" feature --- library/core/tests/iter/mod.rs | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 5b2769d04698d..1a4f10c22fe7d 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -99,3 +99,43 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } + +#[test] +fn test_happy_path_item_in_iterator() { + assert!([1, 2, 3].iter().contain(&1)); +} + +#[test] +fn test_happy_path_item_not_in_iterator() { + assert!(![1, 2, 3].iter().contain(&4)); +} + +#[test] +fn test_edge_case_handling_none_values() { + assert!([Some(2), None].iter().contain(&None)); + assert!([Some(2), None].iter().contain(&Some(2))); +} + +#[test] +fn test_edge_case_handling_empty_iterator() { + assert!(!vec![].iter().contain(&1)); +} + +#[test] +fn test_edge_case_handling_iterator_with_duplicates() { + assert!([1, 2, 2, 3].iter().contain(&2)); +} + +#[test] +fn test_edge_case_handling_iterator_with_custom_struct() { + #[derive(PartialEq)] + struct Item { + value: i32, + } + assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); +} + +#[test] +fn test_edge_case_handling_iterator_with_large_number_of_elements() { + assert!((1..1000).contain(&500)); +} From 48616ce0c589d837bbae983fcc7871812b046db3 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Wed, 10 Jul 2024 21:34:08 +0300 Subject: [PATCH 08/28] added a test for checking that the function can check if a String is in a &str iterator --- library/core/tests/iter/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 1a4f10c22fe7d..95a1660bc6406 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -135,6 +135,12 @@ fn test_edge_case_handling_iterator_with_custom_struct() { assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); } +#[test] +fn test_str_iterator_contain_string() { + assert!([&"a", &"b", &"c"].iter().contain("b".to_string())); + assert!(!&["a", "b", "c"].iter().contain("d".to_string())); +} + #[test] fn test_edge_case_handling_iterator_with_large_number_of_elements() { assert!((1..1000).contain(&500)); From 7ba6c5e53a81a647b3f2c13d9b6d63c174ed1cfc Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Wed, 10 Jul 2024 21:36:03 +0300 Subject: [PATCH 09/28] moved tests for the contains feature to the test file of the Iterator trait --- library/core/tests/iter/mod.rs | 41 ---------------------- library/core/tests/iter/traits/iterator.rs | 35 ++++++++++++++++++ 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 95a1660bc6406..2839e97ebaa53 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -100,47 +100,6 @@ pub fn extend_for_unit() { assert_eq!(x, 5); } -#[test] -fn test_happy_path_item_in_iterator() { - assert!([1, 2, 3].iter().contain(&1)); -} - -#[test] -fn test_happy_path_item_not_in_iterator() { - assert!(![1, 2, 3].iter().contain(&4)); -} - -#[test] -fn test_edge_case_handling_none_values() { - assert!([Some(2), None].iter().contain(&None)); - assert!([Some(2), None].iter().contain(&Some(2))); -} - -#[test] -fn test_edge_case_handling_empty_iterator() { - assert!(!vec![].iter().contain(&1)); -} - -#[test] -fn test_edge_case_handling_iterator_with_duplicates() { - assert!([1, 2, 2, 3].iter().contain(&2)); -} - -#[test] -fn test_edge_case_handling_iterator_with_custom_struct() { - #[derive(PartialEq)] - struct Item { - value: i32, - } - assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); -} - -#[test] -fn test_str_iterator_contain_string() { - assert!([&"a", &"b", &"c"].iter().contain("b".to_string())); - assert!(!&["a", "b", "c"].iter().contain("d".to_string())); -} - #[test] fn test_edge_case_handling_iterator_with_large_number_of_elements() { assert!((1..1000).contain(&500)); diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 93ef9c0812b16..05df70bc4f7b3 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -616,6 +616,41 @@ fn test_next_chunk() { let mut it = std::iter::repeat_with(|| panic!()); assert_eq!(it.next_chunk::<0>().unwrap(), []); } +#[test] +fn test_happy_path_item_not_in_iterator() { + assert!(![1, 2, 3].iter().contain(&4)); +} + +#[test] +fn test_edge_case_handling_none_values() { + assert!([Some(2), None].iter().contain(&None)); + assert!([Some(2), None].iter().contain(&Some(2))); +} + +#[test] +fn test_edge_case_handling_empty_iterator() { + assert!(!vec![].iter().contain(&1)); +} + +#[test] +fn test_edge_case_handling_iterator_with_duplicates() { + assert!([1, 2, 2, 3].iter().contain(&2)); +} + +#[test] +fn test_edge_case_handling_iterator_with_custom_struct() { + #[derive(PartialEq)] + struct Item { + value: i32, + } + assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); +} + +#[test] +fn test_str_iterator_contain_string() { + assert!([&"a", &"b", &"c"].iter().contain("b".to_string())); + assert!(!&["a", "b", "c"].iter().contain("d".to_string())); +} // just tests by whether or not this compiles fn _empty_impl_all_auto_traits<T>() { From b69db01900c5971f93a499ca21fa31ed157fcf37 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Wed, 10 Jul 2024 21:59:18 +0300 Subject: [PATCH 10/28] changed function signature according to the rust library team request --- library/core/src/iter/traits/iterator.rs | 9 +++----- library/core/tests/iter/mod.rs | 5 ---- library/core/tests/iter/traits/iterator.rs | 27 ++++++++++++++++++---- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 1adcda2a4e7cd..4869bbd10fa36 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,5 +1,4 @@ use crate::array; -use crate::borrow::Borrow; use crate::cmp::{self, Ordering}; use crate::num::NonZero; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; @@ -4124,15 +4123,13 @@ pub trait Iterator { /// assert!((1..1000).contain(&500)); /// ``` #[unstable(feature = "contains", reason = "new API", issue = "127494")] - fn contain<Q>(&mut self, item: Q) -> bool + fn contain<Q: Sized>(&mut self, item: Q) -> bool where - Self::Item: PartialEq, - Q: Borrow<Self::Item>, + Self::Item: PartialEq<Q>, Self: Sized, { - let borrowed_item: &Self::Item = item.borrow(); for element in self { - if element == *borrowed_item { + if element == item { return true; } } diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 2839e97ebaa53..5b2769d04698d 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -99,8 +99,3 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } - -#[test] -fn test_edge_case_handling_iterator_with_large_number_of_elements() { - assert!((1..1000).contain(&500)); -} diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 05df70bc4f7b3..90b9ec199718d 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -629,7 +629,7 @@ fn test_edge_case_handling_none_values() { #[test] fn test_edge_case_handling_empty_iterator() { - assert!(!vec![].iter().contain(&1)); + assert!(!Vec::<i32>::new().iter().contain(&1)); } #[test] @@ -646,12 +646,31 @@ fn test_edge_case_handling_iterator_with_custom_struct() { assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); } +// #[test] +// fn test_str_iterator_contain_string() { +// assert!(["a", "b", "c"].iter().contain("b".to_owned())); +// assert!(!["a", "b", "c"].iter().contain("d".to_owned())); +// } + #[test] -fn test_str_iterator_contain_string() { - assert!([&"a", &"b", &"c"].iter().contain("b".to_string())); - assert!(!&["a", "b", "c"].iter().contain("d".to_string())); +fn test_str_iterator_contain_string_slice() { + assert!(["a", "b", "c"].iter().contain(&"b")); + assert!(!["a", "b", "c"].iter().contain(&"d")); } +#[test] +fn test_string_iterator_contain_str_slice() { + assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain("b")); + assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain("d")); +} + + +#[test] +fn test_edge_case_handling_iterator_with_large_number_of_elements() { + assert!((1..1000).contain(500)); +} + + // just tests by whether or not this compiles fn _empty_impl_all_auto_traits<T>() { use std::panic::{RefUnwindSafe, UnwindSafe}; From 3751b5dbfd33c18789b44fac0c58547ceac37a89 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Wed, 10 Jul 2024 22:00:04 +0300 Subject: [PATCH 11/28] removed tests from function doc string --- library/core/src/iter/traits/iterator.rs | 44 ------------------------ 1 file changed, 44 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 4869bbd10fa36..1b4f64ec94d39 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4078,50 +4078,6 @@ pub trait Iterator { /// assert!([Some(2), None].iter().contain(&Some(2))); /// ``` /// - /// Tests: - /// Happy path 1 - the item is in the iterator - /// ``` - /// #![feature(contains)] - /// assert!([1, 2, 3].iter().contain(&1)); - /// ``` - /// Happy path 2 - the item is not in the iterator - /// ``` - /// #![feature(contains)] - /// assert!(![1, 2, 3].iter().contain(&4)); - /// ``` - /// Edge case 1 - handling None values - /// ``` - /// #![feature(contains)] - /// let mut iter = [Some(2), None].iter(); - /// assert!([Some(2), None].iter().contain(&None)); - /// assert!([Some(2), None].iter().contain(&Some(2))); - /// ``` - /// Edge case 2 - handling empty iterator - /// ``` - /// #![feature(contains)] - /// let mut iter: Vec<i32> = vec![]; - /// assert!(!vec![].iter().contain(&1)); - /// ``` - /// Edge case 3 - handling iterator with duplicates - /// ``` - /// #![feature(contains)] - /// let mut iter = [1, 2, 2, 3].iter(); - /// assert!(iter.contain(&2)); - /// ``` - /// Edge case 4 - handling iterator with custom struct - /// ``` - /// #![feature(contains)] - /// #[derive(PartialEq)] - /// struct Item { - /// value: i32, - /// } - /// assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); - /// ``` - /// Edge case 5 - handling iterator with large number of elements - /// ``` - /// #![feature(contains)] - /// assert!((1..1000).contain(&500)); - /// ``` #[unstable(feature = "contains", reason = "new API", issue = "127494")] fn contain<Q: Sized>(&mut self, item: Q) -> bool where From 7ebf719962eb6f0caaf932ebf5dbd3467c33dbea Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Wed, 10 Jul 2024 23:34:53 +0300 Subject: [PATCH 12/28] getting arguments that implement arg == Self::Item and not argument where Self::Item implement Self::Item == arg --- library/core/src/iter/traits/iterator.rs | 27 +++++++++++++++------ library/core/tests/iter/traits/iterator.rs | 28 +++++++++++----------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 1b4f64ec94d39..c56bdf0da02a0 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4072,20 +4072,33 @@ pub trait Iterator { /// Example: /// ``` /// #![feature(contains)] - /// assert!([1, 2, 3].iter().contain(&1)); - /// assert!(![1, 2, 3].iter().contain(&4)); - /// assert!([Some(2), None].iter().contain(&None)); - /// assert!([Some(2), None].iter().contain(&Some(2))); + /// assert!(![1i32, 2i32, 3i32].iter().contain(&4i32)); + /// assert!([Some(2i32), Option::<i32>::None].iter().contain(&None)); + /// assert!([Some(2i32), Option::<i32>::None].iter().contain(&Some(2i32))); + /// assert!(!Vec::<i32>::new().iter().contain(&1i32)); + /// assert!([1i32, 2i32, 2i32, 3i32].iter().contain(&2i32)); + /// #[derive(PartialEq)] + /// struct Item { + /// value: i32, + /// } + /// assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().contain(&Item { value: 2i32 })); + /// assert!(["a", "b", "c"].iter().contain(&"b".to_owned())); + /// assert!(!["a", "b", "c"].iter().contain(&"d".to_owned())); + /// assert!(["a", "b", "c"].iter().contain(&"b")); + /// assert!(!["a", "b", "c"].iter().contain(&"d")); + /// assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"b")); + /// assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"d")); + /// assert!((1..1000).contain(500i32)); /// ``` /// #[unstable(feature = "contains", reason = "new API", issue = "127494")] - fn contain<Q: Sized>(&mut self, item: Q) -> bool + fn contain<Q: ?Sized>(&mut self, item: Q) -> bool where - Self::Item: PartialEq<Q>, + Q: PartialEq<Self::Item>, Self: Sized, { for element in self { - if element == item { + if item == element { return true; } } diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 90b9ec199718d..c2402778028e7 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -618,23 +618,23 @@ fn test_next_chunk() { } #[test] fn test_happy_path_item_not_in_iterator() { - assert!(![1, 2, 3].iter().contain(&4)); + assert!(![1i32, 2i32, 3i32].iter().contain(&4i32)); } #[test] fn test_edge_case_handling_none_values() { - assert!([Some(2), None].iter().contain(&None)); - assert!([Some(2), None].iter().contain(&Some(2))); + assert!([Some(2i32), Option::<i32>::None].iter().contain(&None)); + assert!([Some(2i32), Option::<i32>::None].iter().contain(&Some(2i32))); } #[test] fn test_edge_case_handling_empty_iterator() { - assert!(!Vec::<i32>::new().iter().contain(&1)); + assert!(!Vec::<i32>::new().iter().contain(&1i32)); } #[test] fn test_edge_case_handling_iterator_with_duplicates() { - assert!([1, 2, 2, 3].iter().contain(&2)); + assert!([1i32, 2i32, 2i32, 3i32].iter().contain(&2i32)); } #[test] @@ -643,14 +643,14 @@ fn test_edge_case_handling_iterator_with_custom_struct() { struct Item { value: i32, } - assert!([Item { value: 1 }, Item { value: 2 }].iter().contain(&Item { value: 2 })); + assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().contain(&Item { value: 2i32 })); } -// #[test] -// fn test_str_iterator_contain_string() { -// assert!(["a", "b", "c"].iter().contain("b".to_owned())); -// assert!(!["a", "b", "c"].iter().contain("d".to_owned())); -// } +#[test] +fn test_str_iterator_contain_string() { + assert!(["a", "b", "c"].iter().contain(&"b".to_owned())); + assert!(!["a", "b", "c"].iter().contain(&"d".to_owned())); +} #[test] fn test_str_iterator_contain_string_slice() { @@ -660,14 +660,14 @@ fn test_str_iterator_contain_string_slice() { #[test] fn test_string_iterator_contain_str_slice() { - assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain("b")); - assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain("d")); + assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"b")); + assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"d")); } #[test] fn test_edge_case_handling_iterator_with_large_number_of_elements() { - assert!((1..1000).contain(500)); + assert!((1..1000).contain(500i32)); } From ac8d1e328ffe182be34beda767bf1651271dabaa Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 00:13:58 +0300 Subject: [PATCH 13/28] rust formatting: deleted 2 empty lines --- library/core/tests/iter/traits/iterator.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index c2402778028e7..485f6cff328f2 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -664,13 +664,11 @@ fn test_string_iterator_contain_str_slice() { assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"d")); } - #[test] fn test_edge_case_handling_iterator_with_large_number_of_elements() { assert!((1..1000).contain(500i32)); } - // just tests by whether or not this compiles fn _empty_impl_all_auto_traits<T>() { use std::panic::{RefUnwindSafe, UnwindSafe}; From cd839b80a55f82bb594dfcab63db9e005b4a13b2 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 00:14:37 +0300 Subject: [PATCH 14/28] removed unneeded feature specification --- .../crates/ide-db/src/generated/lints.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 7755a9b9748be..c667dc1e436f8 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -6074,6 +6074,17 @@ The tracking issue for this feature is: None. ------------------------ +"##, + }, + Lint { + label: "contains", + description: r##"# `contains` + +The tracking issue for this feature is: [#94047] + +[#94047]: https://github.com/rust-lang/rust/issues/94047 + + The `rustc` compiler has certain pluggable operations, that is, functionality that isn't hard-coded into the language, but is implemented in libraries, with a special marker to tell the compiler From 66c55b29fad6ea7abf8b3d7e10c63e323e93e733 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 09:11:28 +0300 Subject: [PATCH 15/28] renamed contain to has_item --- library/core/src/iter/traits/iterator.rs | 52 +++++++++++----------- library/core/src/lib.rs | 2 +- library/core/tests/iter/traits/iterator.rs | 32 ++++++------- library/core/tests/lib.rs | 2 +- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c56bdf0da02a0..fc27134207aa3 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -79,10 +79,10 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next(&mut self) -> Option<Self::Item>; - /// 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. /// /// # Examples /// @@ -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 + /// has_items at least `n` elements, otherwise it has_items all of the /// (fewer than `n`) elements of the original iterator. /// /// # Examples @@ -3356,7 +3356,7 @@ pub trait Iterator { Rev::new(self) } - /// Converts an iterator of pairs into a pair of containers. + /// Converts an iterator of pairs into a pair of has_itemers. /// /// `unzip()` consumes an entire iterator of pairs, producing two /// collections: one from the left elements of the pairs, and one @@ -4061,38 +4061,38 @@ pub trait Iterator { unreachable!("Always specialized"); } - /// Checks if the Iterator contains the value. - /// 'contains' is short-circuiting; in other words, it will stop processing - /// as soon as the closure returns `true`. + /// 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. /// /// 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. + /// If the iterator is sorted, or a hash map please use the appropriate method instead. /// /// Example: /// ``` - /// #![feature(contains)] - /// assert!(![1i32, 2i32, 3i32].iter().contain(&4i32)); - /// assert!([Some(2i32), Option::<i32>::None].iter().contain(&None)); - /// assert!([Some(2i32), Option::<i32>::None].iter().contain(&Some(2i32))); - /// assert!(!Vec::<i32>::new().iter().contain(&1i32)); - /// assert!([1i32, 2i32, 2i32, 3i32].iter().contain(&2i32)); + /// #![feature(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().contain(&Item { value: 2i32 })); - /// assert!(["a", "b", "c"].iter().contain(&"b".to_owned())); - /// assert!(!["a", "b", "c"].iter().contain(&"d".to_owned())); - /// assert!(["a", "b", "c"].iter().contain(&"b")); - /// assert!(!["a", "b", "c"].iter().contain(&"d")); - /// assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"b")); - /// assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"d")); - /// assert!((1..1000).contain(500i32)); - /// ``` - /// - #[unstable(feature = "contains", reason = "new API", issue = "127494")] - fn contain<Q: ?Sized>(&mut self, item: Q) -> bool + /// 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)); + /// ``` + /// + #[unstable(feature = "has_item", reason = "new API", issue = "127494")] + fn has_item<Q: ?Sized>(&mut self, item: Q) -> bool where Q: PartialEq<Self::Item>, Self: Sized, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 010d66f7515d6..26d2ae65887a7 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -165,9 +165,9 @@ #![feature(const_unicode_case_lookup)] #![feature(const_unsafecell_get_mut)] #![feature(const_waker)] -#![feature(contains)] #![feature(coverage_attribute)] #![feature(duration_consts_float)] +#![feature(has_item)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 485f6cff328f2..663d710d4bfa5 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -618,23 +618,23 @@ fn test_next_chunk() { } #[test] fn test_happy_path_item_not_in_iterator() { - assert!(![1i32, 2i32, 3i32].iter().contain(&4i32)); + assert!(![1i32, 2i32, 3i32].iter().has_item(&4i32)); } #[test] fn test_edge_case_handling_none_values() { - assert!([Some(2i32), Option::<i32>::None].iter().contain(&None)); - assert!([Some(2i32), Option::<i32>::None].iter().contain(&Some(2i32))); + assert!([Some(2i32), Option::<i32>::None].iter().has_item(&None)); + assert!([Some(2i32), Option::<i32>::None].iter().has_item(&Some(2i32))); } #[test] fn test_edge_case_handling_empty_iterator() { - assert!(!Vec::<i32>::new().iter().contain(&1i32)); + assert!(!Vec::<i32>::new().iter().has_item(&1i32)); } #[test] fn test_edge_case_handling_iterator_with_duplicates() { - assert!([1i32, 2i32, 2i32, 3i32].iter().contain(&2i32)); + assert!([1i32, 2i32, 2i32, 3i32].iter().has_item(&2i32)); } #[test] @@ -643,30 +643,30 @@ fn test_edge_case_handling_iterator_with_custom_struct() { struct Item { value: i32, } - assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().contain(&Item { value: 2i32 })); + assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().has_item(&Item { value: 2i32 })); } #[test] -fn test_str_iterator_contain_string() { - assert!(["a", "b", "c"].iter().contain(&"b".to_owned())); - assert!(!["a", "b", "c"].iter().contain(&"d".to_owned())); +fn test_str_iterator_has_item_string() { + assert!(["a", "b", "c"].iter().has_item(&"b".to_owned())); + assert!(!["a", "b", "c"].iter().has_item(&"d".to_owned())); } #[test] -fn test_str_iterator_contain_string_slice() { - assert!(["a", "b", "c"].iter().contain(&"b")); - assert!(!["a", "b", "c"].iter().contain(&"d")); +fn test_str_iterator_has_item_string_slice() { + assert!(["a", "b", "c"].iter().has_item(&"b")); + assert!(!["a", "b", "c"].iter().has_item(&"d")); } #[test] -fn test_string_iterator_contain_str_slice() { - assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"b")); - assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contain(&"d")); +fn test_string_iterator_has_item_str_slice() { + 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")); } #[test] fn test_edge_case_handling_iterator_with_large_number_of_elements() { - assert!((1..1000).contain(500i32)); + assert!((1..1000).has_item(500i32)); } // just tests by whether or not this compiles diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 72d65f4cc5ebc..87ba99090e94b 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -89,7 +89,7 @@ #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_waker)] -#![feature(contains)] +#![feature(has_item)] #![feature(never_type)] #![feature(unwrap_infallible)] #![feature(pointer_is_aligned_to)] From b67ee443cf17af2934a12f659b510390b080732f Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 09:15:45 +0300 Subject: [PATCH 16/28] renamed feature from has_item to iter_has_item --- library/core/src/iter/traits/iterator.rs | 4 ++-- library/core/src/lib.rs | 2 +- library/core/tests/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index fc27134207aa3..1e974b47a0da3 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4071,7 +4071,7 @@ pub trait Iterator { /// /// Example: /// ``` - /// #![feature(has_item)] + /// #![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))); @@ -4091,7 +4091,7 @@ pub trait Iterator { /// assert!((1..1000).has_item(500i32)); /// ``` /// - #[unstable(feature = "has_item", reason = "new API", issue = "127494")] + #[unstable(feature = "iter_has_item", reason = "new API", issue = "127494")] fn has_item<Q: ?Sized>(&mut self, item: Q) -> bool where Q: PartialEq<Self::Item>, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 26d2ae65887a7..43d7227b28c12 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -167,11 +167,11 @@ #![feature(const_waker)] #![feature(coverage_attribute)] #![feature(duration_consts_float)] -#![feature(has_item)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] #![feature(isqrt)] +#![feature(iter_has_item)] #![feature(link_cfg)] #![feature(offset_of_enum)] #![feature(offset_of_nested)] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 87ba99090e94b..605ac3d38c1bb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -89,7 +89,7 @@ #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_waker)] -#![feature(has_item)] +#![feature(iter_has_item)] #![feature(never_type)] #![feature(unwrap_infallible)] #![feature(pointer_is_aligned_to)] From 1ba1ca7160dbe7d986926bdd6fddc7a6493fb04b Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 09:25:27 +0300 Subject: [PATCH 17/28] added a test for the short-circuiting behaviour --- library/core/tests/iter/traits/iterator.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 663d710d4bfa5..d2db911780e88 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -637,6 +637,17 @@ fn test_edge_case_handling_iterator_with_duplicates() { assert!([1i32, 2i32, 2i32, 3i32].iter().has_item(&2i32)); } +#[test] +/// Tests that short-circuiting works correctly when using `has_item` +/// When you run the function, it should move the iterator forward after the first appearance of the item +fn test_short_circuiting() { + let mut iterator = vec![1, 2, 3, 1, 1].into_iter(); + assert!(iterator.has_item(&1)); + assert_eq!(iterator.next(), Some(2)); + assert!(!iterator.has_item(&4)); + assert_eq!(iterator.next(), None); +} + #[test] fn test_edge_case_handling_iterator_with_custom_struct() { #[derive(PartialEq)] From 934a1941ab114663224f449be5cbd4dfeb0f622b Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 10:55:33 +0300 Subject: [PATCH 18/28] fixed test_short_circuiting --- library/core/tests/iter/traits/iterator.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index d2db911780e88..e69217f144adf 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -641,9 +641,10 @@ fn test_edge_case_handling_iterator_with_duplicates() { /// Tests that short-circuiting works correctly when using `has_item` /// When you run the function, it should move the iterator forward after the first appearance of the item fn test_short_circuiting() { - let mut iterator = vec![1, 2, 3, 1, 1].into_iter(); + let vector = vec![1, 2, 3, 1, 1]; + let mut iterator = vector.iter(); assert!(iterator.has_item(&1)); - assert_eq!(iterator.next(), Some(2)); + assert_eq!(iterator.next(), Some(&2)); assert!(!iterator.has_item(&4)); assert_eq!(iterator.next(), None); } From 3e3ccd8078239d4848c7faf0d9ef388d6e1561c5 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 13:28:58 +0300 Subject: [PATCH 19/28] fixed test_short_circuiting --- library/core/tests/iter/traits/iterator.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index e69217f144adf..2fd3597b635e6 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -641,11 +641,11 @@ fn test_edge_case_handling_iterator_with_duplicates() { /// Tests that short-circuiting works correctly when using `has_item` /// 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![1, 2, 3, 1, 1]; - let mut iterator = vector.iter(); - assert!(iterator.has_item(&1)); - assert_eq!(iterator.next(), Some(&2)); - assert!(!iterator.has_item(&4)); + let vector: Vec<i32> = vec![1i32, 2i32, 3i32, 1i32, 1i32]; + let mut iterator = vector.into_iter(); + assert!(iterator.has_item(1i32)); + assert_eq!(iterator.next(), Some(2)); + assert!(!iterator.has_item(4i32)); assert_eq!(iterator.next(), None); } From bc20afd7963bdd7dde6fd64c5504b48ef7d59c5c Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 14:06:36 +0300 Subject: [PATCH 20/28] renamed feature and function back to contains --- library/core/src/iter/traits/iterator.rs | 46 +++++++++++----------- library/core/src/lib.rs | 2 +- library/core/tests/iter/traits/iterator.rs | 38 +++++++++--------- library/core/tests/lib.rs | 2 +- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 1e974b47a0da3..ebf25c5239b9e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -79,10 +79,10 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next(&mut self) -> Option<Self::Item>; - /// Advances the iterator and returns an array has_iteming the next `N` values. + /// Advances the iterator and returns an array containing the next `N` values. /// /// If there are not enough elements to fill the array then `Err` is returned - /// has_iteming an iterator over the remaining elements. + /// containing an iterator over the remaining elements. /// /// # Examples /// @@ -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 - /// has_items at least `n` elements, otherwise it has_items all of the + /// contains at least `n` elements, otherwise it containss all of the /// (fewer than `n`) elements of the original iterator. /// /// # Examples @@ -3356,7 +3356,7 @@ pub trait Iterator { Rev::new(self) } - /// Converts an iterator of pairs into a pair of has_itemers. + /// Converts an iterator of pairs into a pair of containsers. /// /// `unzip()` consumes an entire iterator of pairs, producing two /// collections: one from the left elements of the pairs, and one @@ -4062,7 +4062,7 @@ pub trait Iterator { } /// Checks if the Iterator has a value. - /// 'has_items' is short-circuiting; in other words, it will stop processing + /// 'contains' is short-circuiting; in other words, it will stop processing /// as soon as the function finds the item in the Iterator. /// /// Performance: @@ -4071,28 +4071,28 @@ pub trait Iterator { /// /// 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)); + /// #![feature(iter_contains)] + /// assert!(![1i32, 2i32, 3i32].iter().contains(&4i32)); + /// assert!([Some(2i32), Option::<i32>::None].iter().contains(&None)); + /// assert!([Some(2i32), Option::<i32>::None].iter().contains(&Some(2i32))); + /// assert!(!Vec::<i32>::new().iter().contains(&1i32)); + /// assert!([1i32, 2i32, 2i32, 3i32].iter().contains(&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)); - /// ``` - /// - #[unstable(feature = "iter_has_item", reason = "new API", issue = "127494")] - fn has_item<Q: ?Sized>(&mut self, item: Q) -> bool + /// assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().contains(&Item { value: 2i32 })); + /// assert!(["a", "b", "c"].iter().contains(&"b".to_owned())); + /// assert!(!["a", "b", "c"].iter().contains(&"d".to_owned())); + /// assert!(["a", "b", "c"].iter().contains(&"b")); + /// assert!(!["a", "b", "c"].iter().contains(&"d")); + /// assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"b")); + /// assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"d")); + /// assert!((1..1000).contains(500i32)); + /// ``` + /// + #[unstable(feature = "iter_contains", reason = "new API", issue = "127494")] + fn contains<Q: ?Sized>(&mut self, item: Q) -> bool where Q: PartialEq<Self::Item>, Self: Sized, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 43d7227b28c12..1bfffa0f58dd4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -171,7 +171,7 @@ #![feature(ip)] #![feature(is_ascii_octdigit)] #![feature(isqrt)] -#![feature(iter_has_item)] +#![feature(iter_contains)] #![feature(link_cfg)] #![feature(offset_of_enum)] #![feature(offset_of_nested)] diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 2fd3597b635e6..3dd2443a8c463 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -618,34 +618,34 @@ fn test_next_chunk() { } #[test] fn test_happy_path_item_not_in_iterator() { - assert!(![1i32, 2i32, 3i32].iter().has_item(&4i32)); + assert!(![1i32, 2i32, 3i32].iter().contains(&4i32)); } #[test] fn test_edge_case_handling_none_values() { - assert!([Some(2i32), Option::<i32>::None].iter().has_item(&None)); - assert!([Some(2i32), Option::<i32>::None].iter().has_item(&Some(2i32))); + 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().has_item(&1i32)); + assert!(!Vec::<i32>::new().iter().contains(&1i32)); } #[test] fn test_edge_case_handling_iterator_with_duplicates() { - assert!([1i32, 2i32, 2i32, 3i32].iter().has_item(&2i32)); + assert!([1i32, 2i32, 2i32, 3i32].iter().contains(&2i32)); } #[test] -/// Tests that short-circuiting works correctly when using `has_item` +/// 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.has_item(1i32)); + assert!(iterator.contains(1i32)); assert_eq!(iterator.next(), Some(2)); - assert!(!iterator.has_item(4i32)); + assert!(!iterator.contains(4i32)); assert_eq!(iterator.next(), None); } @@ -655,30 +655,30 @@ fn test_edge_case_handling_iterator_with_custom_struct() { struct Item { value: i32, } - assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().has_item(&Item { value: 2i32 })); + assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().contains(&Item { value: 2i32 })); } #[test] -fn test_str_iterator_has_item_string() { - assert!(["a", "b", "c"].iter().has_item(&"b".to_owned())); - assert!(!["a", "b", "c"].iter().has_item(&"d".to_owned())); +fn test_str_iterator_contains_string() { + assert!(["a", "b", "c"].iter().contains(&"b".to_owned())); + assert!(!["a", "b", "c"].iter().contains(&"d".to_owned())); } #[test] -fn test_str_iterator_has_item_string_slice() { - assert!(["a", "b", "c"].iter().has_item(&"b")); - assert!(!["a", "b", "c"].iter().has_item(&"d")); +fn test_str_iterator_contains_string_slice() { + assert!(["a", "b", "c"].iter().contains(&"b")); + assert!(!["a", "b", "c"].iter().contains(&"d")); } #[test] -fn test_string_iterator_has_item_str_slice() { - 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")); +fn test_string_iterator_contains_str_slice() { + assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"b")); + assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"d")); } #[test] fn test_edge_case_handling_iterator_with_large_number_of_elements() { - assert!((1..1000).has_item(500i32)); + assert!((1..1000).contains(500i32)); } // just tests by whether or not this compiles diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 605ac3d38c1bb..08d633b3c2c6f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -89,7 +89,7 @@ #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_waker)] -#![feature(iter_has_item)] +#![feature(iter_contains)] #![feature(never_type)] #![feature(unwrap_infallible)] #![feature(pointer_is_aligned_to)] From 8a7c12bc45b69b6f7d25794d636d67a785bbc25e Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 14:07:48 +0300 Subject: [PATCH 21/28] changed excepted compiler suggestion. Now the compiler is suggesting to use the function contains of the Iterator trait --- tests/ui/suggestions/deref-path-method.rs | 2 +- tests/ui/suggestions/deref-path-method.stderr | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/ui/suggestions/deref-path-method.rs b/tests/ui/suggestions/deref-path-method.rs index 0281cdb6b37cf..03cca7f8e582f 100644 --- a/tests/ui/suggestions/deref-path-method.rs +++ b/tests/ui/suggestions/deref-path-method.rs @@ -1,6 +1,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 `[_]` } diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index b27d9aef06614..568e6f97e9752 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -1,8 +1,8 @@ -error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope +error[E0599]: `Vec<_, _>` is not an iterator --> $DIR/deref-path-method.rs:3:10 | LL | Vec::contains(&vec, &0); - | ^^^^^^^^ function or associated item not found in `Vec<_, _>` + | ^^^^^^^^ `Vec<_, _>` is not an iterator | note: if you're trying to build a new `Vec<_, _>` consider using one of the following associated functions: Vec::<T>::new @@ -11,6 +11,9 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll Vec::<T>::from_raw_parts and 4 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + = note: the following trait bounds were not satisfied: + `Vec<_, _>: Iterator` + which is required by `&mut Vec<_, _>: Iterator` help: the function `contains` is implemented on `[_]` | LL | <[_]>::contains(&vec, &0); From dac6cd709295de581f0474175aee7affe8d7935f Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 14:09:46 +0300 Subject: [PATCH 22/28] deleted a test that uses the function contains of a range --- library/core/tests/iter/traits/iterator.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 3dd2443a8c463..d2244b9aa3307 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -676,11 +676,6 @@ fn test_string_iterator_contains_str_slice() { assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"d")); } -#[test] -fn test_edge_case_handling_iterator_with_large_number_of_elements() { - assert!((1..1000).contains(500i32)); -} - // just tests by whether or not this compiles fn _empty_impl_all_auto_traits<T>() { use std::panic::{RefUnwindSafe, UnwindSafe}; From 2a32a8c729acc2f7195e0000af8a3f2fe3bbb9c5 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 14:18:34 +0300 Subject: [PATCH 23/28] deleted a test that uses the function contains of a range --- library/core/src/iter/traits/iterator.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index ebf25c5239b9e..c174b760b94e3 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4088,7 +4088,6 @@ pub trait Iterator { /// assert!(!["a", "b", "c"].iter().contains(&"d")); /// assert!(["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"b")); /// assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"d")); - /// assert!((1..1000).contains(500i32)); /// ``` /// #[unstable(feature = "iter_contains", reason = "new API", issue = "127494")] From ba5b980df3bd86a7ed58e691bc28590f77810bd3 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 14:43:33 +0300 Subject: [PATCH 24/28] removed the contains feature from library/core/Cargo.toml --- library/core/Cargo.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 8ffa0d831da9a..cace4582b489a 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -36,8 +36,6 @@ optimize_for_size = [] # Make `RefCell` store additional debugging information, which is printed out when # a borrow error occurs debug_refcell = [] -# Adds a function to check if an element is contained in an iterator -contains = [] [lints.rust.unexpected_cfgs] level = "warn" From e70effd9a76ba8e711dd9cc1589ca45afb93f96f Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 14:50:44 +0300 Subject: [PATCH 25/28] made the doc tests small and simple --- library/core/src/iter/traits/iterator.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c174b760b94e3..1317d19b55ffa 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4072,22 +4072,12 @@ pub trait Iterator { /// Example: /// ``` /// #![feature(iter_contains)] - /// assert!(![1i32, 2i32, 3i32].iter().contains(&4i32)); - /// assert!([Some(2i32), Option::<i32>::None].iter().contains(&None)); - /// assert!([Some(2i32), Option::<i32>::None].iter().contains(&Some(2i32))); - /// assert!(!Vec::<i32>::new().iter().contains(&1i32)); - /// assert!([1i32, 2i32, 2i32, 3i32].iter().contains(&2i32)); - /// #[derive(PartialEq)] - /// struct Item { - /// value: i32, - /// } - /// assert!([Item { value: 1i32 }, Item { value: 2i32 }].iter().contains(&Item { value: 2i32 })); + /// 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())); - /// assert!(!["a", "b", "c"].iter().contains(&"d".to_owned())); - /// assert!(["a", "b", "c"].iter().contains(&"b")); - /// assert!(!["a", "b", "c"].iter().contains(&"d")); + /// // 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")); - /// assert!(!["a".to_owned(), "b".to_owned(), "c".to_owned()].iter().contains(&"d")); /// ``` /// #[unstable(feature = "iter_contains", reason = "new API", issue = "127494")] From 82b6b103ca4e93ddc55b1fc8b0b998a128a6f4d8 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 14:54:07 +0300 Subject: [PATCH 26/28] made the docs more consistent with similar methods of other types --- library/core/src/iter/traits/iterator.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 1317d19b55ffa..c8d7af3900687 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4061,9 +4061,10 @@ pub trait Iterator { unreachable!("Always specialized"); } - /// Checks if the Iterator has a value. + /// Returns `true` if the iterator contains a value. + /// /// 'contains' is short-circuiting; in other words, it will stop processing - /// as soon as the function finds the item in the Iterator. + /// as soon as the function finds the item in the `Iterator`. /// /// Performance: /// This method checks the whole iterator, which takes O(n) time. From 2f726708c013ec1b8b78a325c346ba78f54f3241 Mon Sep 17 00:00:00 2001 From: Yoni Kremer <yoni.kremer@gmail.com> Date: Thu, 11 Jul 2024 20:04:48 +0300 Subject: [PATCH 27/28] fixed typos Co-authored-by: Juniper Tyree <50025784+juntyr@users.noreply.github.com> --- library/core/src/iter/traits/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c8d7af3900687..f5e952e1a5aba 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3356,7 +3356,7 @@ pub trait Iterator { Rev::new(self) } - /// Converts an iterator of pairs into a pair of containsers. + /// Converts an iterator of pairs into a pair of containers. /// /// `unzip()` consumes an entire iterator of pairs, producing two /// collections: one from the left elements of the pairs, and one From fb989752507d9f67f5908f01d3a8276bfa1cd4b1 Mon Sep 17 00:00:00 2001 From: yoni <yoni.kremer@gmail.com> Date: Fri, 12 Jul 2024 15:55:31 +0300 Subject: [PATCH 28/28] improved doc example --- library/core/src/iter/traits/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index c8d7af3900687..348dddcb5a431 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4073,7 +4073,7 @@ pub trait Iterator { /// Example: /// ``` /// #![feature(iter_contains)] - /// assert!([1, 2, 3].iter().contains(&1)); + /// assert!([1, 2, 3].iter().map(|&x| x * 3).contains(&6)); /// 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()));