@@ -1146,6 +1146,38 @@ where
11461146 }
11471147}
11481148
1149+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1150+ impl < T , S > BitOr < HashSet < T , S > > for HashSet < T , S >
1151+ where
1152+ T : Eq + Hash ,
1153+ S : BuildHasher ,
1154+ {
1155+ type Output = HashSet < T , S > ;
1156+
1157+ /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`.
1158+ ///
1159+ /// # Examples
1160+ ///
1161+ /// ```
1162+ /// use std::collections::HashSet;
1163+ ///
1164+ /// let a = HashSet::from([1, 2, 3]);
1165+ /// let b = HashSet::from([3, 4, 5]);
1166+ ///
1167+ /// let result = a | b;
1168+ /// assert_eq!(result, HashSet::from([1, 2, 3, 4, 5]));
1169+ /// ```
1170+ fn bitor ( self , rhs : HashSet < T , S > ) -> HashSet < T , S > {
1171+ // Try to avoid allocations by keeping set with the bigger capacity,
1172+ // try to avoid unnecessary moves, by keeping set with the bigger length
1173+ let [ a, mut b] = minmax_by_key ( self , rhs, |set| ( set. capacity ( ) , set. len ( ) ) ) ;
1174+
1175+ b. extend ( a) ;
1176+
1177+ b
1178+ }
1179+ }
1180+
11491181#[ stable( feature = "rust1" , since = "1.0.0" ) ]
11501182impl < T , S > BitAnd < & HashSet < T , S > > for & HashSet < T , S >
11511183where
@@ -1172,6 +1204,33 @@ where
11721204 }
11731205}
11741206
1207+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1208+ impl < T , S > BitAnd < & HashSet < T , S > > for HashSet < T , S >
1209+ where
1210+ T : Eq + Hash ,
1211+ S : BuildHasher ,
1212+ {
1213+ type Output = HashSet < T , S > ;
1214+
1215+ /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`.
1216+ ///
1217+ /// # Examples
1218+ ///
1219+ /// ```
1220+ /// use std::collections::HashSet;
1221+ ///
1222+ /// let a = HashSet::from([1, 2, 3]);
1223+ /// let b = HashSet::from([2, 3, 4]);
1224+ ///
1225+ /// let result = a & &b;
1226+ /// assert_eq!(result, HashSet::from([2, 3]));
1227+ /// ```
1228+ fn bitand ( mut self , rhs : & HashSet < T , S > ) -> HashSet < T , S > {
1229+ self . retain ( |e| rhs. contains ( e) ) ;
1230+ self
1231+ }
1232+ }
1233+
11751234#[ stable( feature = "rust1" , since = "1.0.0" ) ]
11761235impl < T , S > BitXor < & HashSet < T , S > > for & HashSet < T , S >
11771236where
@@ -1198,6 +1257,41 @@ where
11981257 }
11991258}
12001259
1260+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1261+ impl < T , S > BitXor < HashSet < T , S > > for HashSet < T , S >
1262+ where
1263+ T : Eq + Hash ,
1264+ S : BuildHasher ,
1265+ {
1266+ type Output = HashSet < T , S > ;
1267+
1268+ /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`.
1269+ ///
1270+ /// # Examples
1271+ ///
1272+ /// ```
1273+ /// use std::collections::HashSet;
1274+ ///
1275+ /// let a = HashSet::from([1, 2, 3]);
1276+ /// let b = HashSet::from([3, 4, 5]);
1277+ ///
1278+ /// let result = a ^ b;
1279+ /// assert_eq!(result, HashSet::from([1, 2, 4, 5]));
1280+ /// ```
1281+ fn bitxor ( self , rhs : HashSet < T , S > ) -> HashSet < T , S > {
1282+ // Iterate through the smaller set
1283+ let [ mut a, mut b] = minmax_by_key ( self , rhs, HashSet :: len) ;
1284+
1285+ // This is essentially
1286+ // a = a - b (retain elements that are *not* in b)
1287+ // b = b - a (remove all elements that are in a)
1288+ a. retain ( |e| !b. remove ( e) ) ;
1289+
1290+ // Union of the differences
1291+ a | b
1292+ }
1293+ }
1294+
12011295#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12021296impl < T , S > Sub < & HashSet < T , S > > for & HashSet < T , S >
12031297where
@@ -1224,6 +1318,41 @@ where
12241318 }
12251319}
12261320
1321+ #[ stable( feature = "set_owned_ops" , since = "CURRENT_RUSTC_VERSION" ) ]
1322+ impl < T , S > Sub < & HashSet < T , S > > for HashSet < T , S >
1323+ where
1324+ T : Eq + Hash ,
1325+ S : BuildHasher ,
1326+ {
1327+ type Output = HashSet < T , S > ;
1328+
1329+ /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`.
1330+ ///
1331+ /// # Examples
1332+ ///
1333+ /// ```
1334+ /// use std::collections::HashSet;
1335+ ///
1336+ /// let a = HashSet::from([1, 2, 3]);
1337+ /// let b = HashSet::from([3, 4, 5]);
1338+ ///
1339+ /// let result = a - &b;
1340+ /// assert_eq!(result, HashSet::from([1, 2]));
1341+ /// ```
1342+ fn sub ( mut self , rhs : & HashSet < T , S > ) -> HashSet < T , S > {
1343+ // Iterate the smaller set, removing elements that are in `rhs` from `self`
1344+ if self . len ( ) <= rhs. len ( ) {
1345+ self . retain ( |e| !rhs. contains ( e) ) ;
1346+ } else {
1347+ rhs. iter ( ) . for_each ( |e| {
1348+ self . remove ( e) ;
1349+ } )
1350+ }
1351+
1352+ self
1353+ }
1354+ }
1355+
12271356/// An iterator over the items of a `HashSet`.
12281357///
12291358/// This `struct` is created by the [`iter`] method on [`HashSet`].
@@ -1815,3 +1944,7 @@ fn assert_covariance() {
18151944 d
18161945 }
18171946}
1947+
1948+ fn minmax_by_key < T , K : Ord > ( a : T , b : T , k : impl Fn ( & T ) -> K ) -> [ T ; 2 ] {
1949+ if k ( & a) <= k ( & b) { [ a, b] } else { [ b, a] }
1950+ }
0 commit comments