@@ -153,7 +153,7 @@ macro_rules! unindexed_range_impl {
153
153
{
154
154
if let Some ( len) = self . opt_len( ) {
155
155
( 0 ..len) . into_par_iter( )
156
- . map( |i| self . range. start + i as $t)
156
+ . map( |i| self . range. start. wrapping_add ( i as $t) )
157
157
. drive_unindexed( consumer)
158
158
} else {
159
159
bridge_unindexed( IterProducer { range: self . range } , consumer)
@@ -211,7 +211,7 @@ unindexed_range_impl!{i64, u64}
211
211
#[ cfg( has_i128) ] unindexed_range_impl ! { i128 , u128 }
212
212
213
213
#[ test]
214
- pub fn check_range_split_at_overflow ( ) {
214
+ fn check_range_split_at_overflow ( ) {
215
215
// Note, this split index overflows i8!
216
216
let producer = IterProducer { range : -100i8 ..100 } ;
217
217
let ( left, right) = producer. split_at ( 150 ) ;
@@ -222,7 +222,7 @@ pub fn check_range_split_at_overflow() {
222
222
223
223
#[ cfg( has_i128) ]
224
224
#[ test]
225
- pub fn test_i128_len_doesnt_overflow ( ) {
225
+ fn test_i128_len_doesnt_overflow ( ) {
226
226
use std:: { i128, u128} ;
227
227
228
228
// Using parse because some versions of rust don't allow long literals
@@ -238,7 +238,7 @@ pub fn test_i128_len_doesnt_overflow() {
238
238
}
239
239
240
240
#[ test]
241
- pub fn test_u64_opt_len ( ) {
241
+ fn test_u64_opt_len ( ) {
242
242
use std:: { u64, usize} ;
243
243
assert_eq ! ( Some ( 100 ) , ( 0 ..100u64 ) . into_par_iter( ) . opt_len( ) ) ;
244
244
assert_eq ! ( Some ( usize :: MAX ) , ( 0 ..usize :: MAX as u64 ) . into_par_iter( ) . opt_len( ) ) ;
@@ -250,10 +250,26 @@ pub fn test_u64_opt_len() {
250
250
251
251
#[ cfg( has_i128) ]
252
252
#[ test]
253
- pub fn test_u128_opt_len ( ) {
253
+ fn test_u128_opt_len ( ) {
254
254
use std:: { u128, usize} ;
255
255
assert_eq ! ( Some ( 100 ) , ( 0 ..100u128 ) . into_par_iter( ) . opt_len( ) ) ;
256
256
assert_eq ! ( Some ( usize :: MAX ) , ( 0 ..usize :: MAX as u128 ) . into_par_iter( ) . opt_len( ) ) ;
257
257
assert_eq ! ( None , ( 0 ..1 + usize :: MAX as u128 ) . into_par_iter( ) . opt_len( ) ) ;
258
258
assert_eq ! ( None , ( 0 ..u128 :: MAX ) . into_par_iter( ) . opt_len( ) ) ;
259
259
}
260
+
261
+ // `usize as i64` can overflow, so make sure to wrap it appropriately
262
+ // when using the `opt_len` "indexed" mode.
263
+ #[ test]
264
+ #[ cfg( target_pointer_width = "64" ) ]
265
+ fn test_usize_i64_overflow ( ) {
266
+ use std:: i64;
267
+ use ThreadPoolBuilder ;
268
+
269
+ let iter = ( -2 ..i64:: MAX ) . into_par_iter ( ) ;
270
+ assert_eq ! ( iter. opt_len( ) , Some ( i64 :: MAX as usize + 2 ) ) ;
271
+
272
+ // always run with multiple threads to split into, or this will take forever...
273
+ let pool = ThreadPoolBuilder :: new ( ) . num_threads ( 8 ) . build ( ) . unwrap ( ) ;
274
+ pool. install ( || assert_eq ! ( iter. find_last( |_| true ) , Some ( i64 :: MAX - 1 ) ) ) ;
275
+ }
0 commit comments