@@ -515,8 +515,13 @@ macro_rules! uint_impl {
515515 ///
516516 /// # Panics
517517 ///
518- /// This function will panic if `n` is greater than or equal to the number of
519- /// bits in `self`.
518+ /// ## Overflow behavior
519+ ///
520+ /// If overflow checks are enabled (default in debug mode), this function will panic if `n`
521+ /// is greater than or equal to the number of bits in `self`. If overflow checks are
522+ /// disabled (default in release mode), there is no panic; instead, the value is shifted
523+ /// by `n % Self::BITS`.
524+ // FIXME(wrapping_funnel_shifts): link to `wrapping_funnel_shl` when stable.
520525 ///
521526 /// # Examples
522527 ///
@@ -543,21 +548,31 @@ macro_rules! uint_impl {
543548 ///
544549 /// ```should_panic
545550 /// #![feature(funnel_shifts)]
551+ /// # #![feature(cfg_overflow_checks)]
552+ /// # #[cfg(overflow_checks)] {
546553 ///
547554 #[ doc = concat!( "let a = " , stringify!( $SelfT) , "::MAX;" ) ]
548555 /// // Okay
549556 #[ doc = concat!( "let _ = a.rotate_left(" , stringify!( $SelfT) , "::BITS);" ) ]
550- /// // Panics
557+ /// // Panics (only when overflow checks are enabled)
551558 #[ doc = concat!( "let _ = a.funnel_shl(a, " , stringify!( $SelfT) , "::BITS);" ) ]
559+ /// # }
560+ /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic");
552561 /// ```
553562 #[ rustc_const_unstable( feature = "funnel_shifts" , issue = "145686" ) ]
554563 #[ unstable( feature = "funnel_shifts" , issue = "145686" ) ]
555564 #[ must_use = "this returns the result of the operation, without modifying the original" ]
556565 #[ inline( always) ]
566+ #[ rustc_inherit_overflow_checks]
557567 pub const fn funnel_shl( self , right: Self , n: u32 ) -> Self {
558- assert!( n < Self :: BITS , "attempt to funnel shift left with overflow" ) ;
559- // SAFETY: just checked that `shift` is in-range
560- unsafe { self . unchecked_funnel_shl( right, n) }
568+ if intrinsics:: overflow_checks( ) {
569+ assert!( n < Self :: BITS , "attempt to funnel shift left with overflow" ) ;
570+ }
571+ // SAFETY: `n` is wrapped to within range
572+ unsafe {
573+ let n = n & ( Self :: BITS - 1 ) ;
574+ self . unchecked_funnel_shl( right, n)
575+ }
561576 }
562577
563578 /// Performs a right funnel shift.
@@ -571,8 +586,13 @@ macro_rules! uint_impl {
571586 ///
572587 /// # Panics
573588 ///
574- /// This function will panic if `n` is greater than or equal to the number of
575- /// bits in `self`.
589+ /// ## Overflow behavior
590+ ///
591+ /// If overflow checks are enabled (default in debug mode), this function will panic if `n`
592+ /// is greater than or equal to the number of bits in `self`. If overflow checks are
593+ /// disabled (default in release mode), there is no panic; instead, the value is shifted
594+ /// by `n % Self::BITS`.
595+ // FIXME(wrapping_funnel_shifts): link to `wrapping_funnel_shr` when stable.
576596 ///
577597 /// # Examples
578598 ///
@@ -599,21 +619,31 @@ macro_rules! uint_impl {
599619 ///
600620 /// ```should_panic
601621 /// #![feature(funnel_shifts)]
622+ /// # #![feature(cfg_overflow_checks)]
623+ /// # #[cfg(overflow_checks)] {
602624 ///
603625 #[ doc = concat!( "let a = " , stringify!( $SelfT) , "::MAX;" ) ]
604626 /// // Okay
605627 #[ doc = concat!( "let _ = a.rotate_right(" , stringify!( $SelfT) , "::BITS);" ) ]
606- /// // Panics
628+ /// // Panics (only when overflow checks are enabled)
607629 #[ doc = concat!( "let _ = a.funnel_shr(a, " , stringify!( $SelfT) , "::BITS);" ) ]
630+ /// # }
631+ /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic");
608632 /// ```
609633 #[ rustc_const_unstable( feature = "funnel_shifts" , issue = "145686" ) ]
610634 #[ unstable( feature = "funnel_shifts" , issue = "145686" ) ]
611635 #[ must_use = "this returns the result of the operation, without modifying the original" ]
612636 #[ inline( always) ]
637+ #[ rustc_inherit_overflow_checks]
613638 pub const fn funnel_shr( self , right: Self , n: u32 ) -> Self {
614- assert!( n < Self :: BITS , "attempt to funnel shift right with overflow" ) ;
615- // SAFETY: just checked that `shift` is in-range
616- unsafe { self . unchecked_funnel_shr( right, n) }
639+ if intrinsics:: overflow_checks( ) {
640+ assert!( n < Self :: BITS , "attempt to funnel shift right with overflow" ) ;
641+ }
642+ // SAFETY: `n` is wrapped to within range
643+ unsafe {
644+ let n = n & ( Self :: BITS - 1 ) ;
645+ self . unchecked_funnel_shr( right, n)
646+ }
617647 }
618648
619649 /// Unchecked funnel shift left.
0 commit comments