@@ -271,13 +271,19 @@ macro_rules! uint_module {
271271 assert_eq!( from_str:: <$T>( "x" ) , None ) ;
272272 }
273273
274- // Not const because `catch_unwind` is not const yet.
274+ // Not const because overflow always panics during const evaluation, and
275+ // `catch_unwind` is not const yet.
275276 #[ test]
276- fn strict_pow ( ) {
277+ fn panicking_pow ( ) {
277278 use std:: panic:: catch_unwind;
278279
279280 {
280281 const R : $T = 0 ;
282+ assert_eq!( R . pow( 0 ) , 1 as $T) ;
283+ assert_eq!( R . pow( 1 ) , 0 as $T) ;
284+ assert_eq!( R . pow( 2 ) , 0 as $T) ;
285+ assert_eq!( R . pow( 128 ) , 0 as $T) ;
286+
281287 assert_eq!( R . strict_pow( 0 ) , 1 as $T) ;
282288 assert_eq!( R . strict_pow( 1 ) , 0 as $T) ;
283289 assert_eq!( R . strict_pow( 2 ) , 0 as $T) ;
@@ -286,6 +292,11 @@ macro_rules! uint_module {
286292
287293 {
288294 const R : $T = 1 ;
295+ assert_eq!( R . pow( 0 ) , 1 as $T) ;
296+ assert_eq!( R . pow( 1 ) , 1 as $T) ;
297+ assert_eq!( R . pow( 2 ) , 1 as $T) ;
298+ assert_eq!( R . pow( 128 ) , 1 as $T) ;
299+
289300 assert_eq!( R . strict_pow( 0 ) , 1 as $T) ;
290301 assert_eq!( R . strict_pow( 1 ) , 1 as $T) ;
291302 assert_eq!( R . strict_pow( 2 ) , 1 as $T) ;
@@ -294,48 +305,24 @@ macro_rules! uint_module {
294305
295306 {
296307 const R : $T = 2 ;
308+ assert_eq!( R . pow( 0 ) , 1 as $T) ;
309+ assert_eq!( R . pow( 1 ) , 2 as $T) ;
310+ assert_eq!( R . pow( 2 ) , 4 as $T) ;
311+ assert_eq!( R . pow( 128 ) , 0 as $T) ;
312+ assert_eq!( R . pow( 129 ) , 0 as $T) ;
313+
297314 assert_eq!( R . strict_pow( 0 ) , 1 as $T) ;
298315 assert_eq!( R . strict_pow( 1 ) , 2 as $T) ;
299316 assert_eq!( R . strict_pow( 2 ) , 4 as $T) ;
300317 assert!( catch_unwind( || R . strict_pow( 128 ) ) . is_err( ) ) ;
301318 }
302319
320+ // If `k * exp` wraps around into a valid shift amount, `pow` should still return 0/panic
303321 {
304- const R : $T = $T:: MAX ;
305- assert_eq!( R . strict_pow( 0 ) , 1 as $T) ;
306- assert_eq!( R . strict_pow( 1 ) , R as $T) ;
307- assert!( catch_unwind( || R . strict_pow( 2 ) ) . is_err( ) ) ;
308- assert!( catch_unwind( || R . strict_pow( 128 ) ) . is_err( ) ) ;
309- }
310- }
311-
312- // Not const because overflow always panics during const evaluation, and
313- // `catch_unwind` is not const yet.
314- #[ test]
315- fn pow( ) {
316- {
317- const R : $T = 0 ;
318- assert_eq!( R . pow( 0 ) , 1 as $T) ;
319- assert_eq!( R . pow( 1 ) , 0 as $T) ;
320- assert_eq!( R . pow( 2 ) , 0 as $T) ;
321- assert_eq!( R . pow( 128 ) , 0 as $T) ;
322- }
323-
324- {
325- const R : $T = 1 ;
326- assert_eq!( R . pow( 0 ) , 1 as $T) ;
327- assert_eq!( R . pow( 1 ) , 1 as $T) ;
328- assert_eq!( R . pow( 2 ) , 1 as $T) ;
329- assert_eq!( R . pow( 128 ) , 1 as $T) ;
330- }
331-
332- {
333- const R : $T = 2 ;
334- assert_eq!( R . pow( 0 ) , 1 as $T) ;
335- assert_eq!( R . pow( 1 ) , 2 as $T) ;
336- assert_eq!( R . pow( 2 ) , 4 as $T) ;
337- assert_eq!( R . pow( 128 ) , 0 as $T) ;
338- assert_eq!( R . pow( 129 ) , 0 as $T) ;
322+ const R : $T = 4 ;
323+ const HALF : u32 = u32 :: MAX / 2 + 1 ;
324+ assert_eq!( R . pow( HALF ) , 0 as $T) ;
325+ assert!( catch_unwind( || R . strict_pow( HALF ) ) . is_err( ) ) ;
339326 }
340327
341328 {
@@ -345,6 +332,11 @@ macro_rules! uint_module {
345332 assert_eq!( R . pow( 2 ) , 1 as $T) ;
346333 assert_eq!( R . pow( 128 ) , 1 as $T) ;
347334 assert_eq!( R . pow( 129 ) , R as $T) ;
335+
336+ assert_eq!( R . strict_pow( 0 ) , 1 as $T) ;
337+ assert_eq!( R . strict_pow( 1 ) , R as $T) ;
338+ assert!( catch_unwind( || R . strict_pow( 2 ) ) . is_err( ) ) ;
339+ assert!( catch_unwind( || R . strict_pow( 128 ) ) . is_err( ) ) ;
348340 }
349341 }
350342
@@ -443,6 +435,17 @@ macro_rules! uint_module {
443435 assert_eq_const_safe!( $T: R . saturating_pow( 129 ) , $T:: MAX ) ;
444436 }
445437
438+ // overflow in the shift caclculation should result in the final
439+ // result being 0 rather than accidentally succeeding due to a
440+ // shift within the word size
441+ // ie `4 ** 0x8000_0000` should give 0 rather than 1 << 0
442+ {
443+ const R : $T = 4 ;
444+ const HALF : u32 = u32 :: MAX / 2 + 1 ;
445+ assert_eq_const_safe!( $T: R . wrapping_pow( HALF ) , 0 as $T) ;
446+ assert_eq_const_safe!( ( $T, bool ) : R . overflowing_pow( HALF ) , ( 0 as $T, true ) ) ;
447+ }
448+
446449 {
447450 const R : $T = $T:: MAX ;
448451 assert_eq_const_safe!( $T: R . wrapping_pow( 0 ) , 1 as $T) ;
0 commit comments