@@ -267,8 +267,9 @@ $EndFeature, "
267267```
268268" ) ,
269269 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
270+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
270271 #[ inline]
271- pub fn count_ones( self ) -> u32 { ( self as $UnsignedT) . count_ones( ) }
272+ pub const fn count_ones( self ) -> u32 { ( self as $UnsignedT) . count_ones( ) }
272273 }
273274
274275 doc_comment! {
@@ -282,8 +283,9 @@ Basic usage:
282283" , $Feature, "assert_eq!(" , stringify!( $SelfT) , "::max_value().count_zeros(), 1);" , $EndFeature, "
283284```" ) ,
284285 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
286+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
285287 #[ inline]
286- pub fn count_zeros( self ) -> u32 {
288+ pub const fn count_zeros( self ) -> u32 {
287289 ( !self ) . count_ones( )
288290 }
289291 }
@@ -302,8 +304,9 @@ assert_eq!(n.leading_zeros(), 0);",
302304$EndFeature, "
303305```" ) ,
304306 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
307+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
305308 #[ inline]
306- pub fn leading_zeros( self ) -> u32 {
309+ pub const fn leading_zeros( self ) -> u32 {
307310 ( self as $UnsignedT) . leading_zeros( )
308311 }
309312 }
@@ -322,8 +325,9 @@ assert_eq!(n.trailing_zeros(), 2);",
322325$EndFeature, "
323326```" ) ,
324327 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
328+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
325329 #[ inline]
326- pub fn trailing_zeros( self ) -> u32 {
330+ pub const fn trailing_zeros( self ) -> u32 {
327331 ( self as $UnsignedT) . trailing_zeros( )
328332 }
329333 }
@@ -396,8 +400,9 @@ $EndFeature, "
396400 /// assert_eq!(m, 21760);
397401 /// ```
398402 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
403+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
399404 #[ inline]
400- pub fn swap_bytes( self ) -> Self {
405+ pub const fn swap_bytes( self ) -> Self {
401406 ( self as $UnsignedT) . swap_bytes( ) as Self
402407 }
403408
@@ -447,9 +452,17 @@ if cfg!(target_endian = \"big\") {
447452$EndFeature, "
448453```" ) ,
449454 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
455+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
450456 #[ inline]
451- pub fn from_be( x: Self ) -> Self {
452- if cfg!( target_endian = "big" ) { x } else { x. swap_bytes( ) }
457+ pub const fn from_be( x: Self ) -> Self {
458+ #[ cfg( target_endian = "big" ) ]
459+ {
460+ x
461+ }
462+ #[ cfg( not( target_endian = "big" ) ) ]
463+ {
464+ x. swap_bytes( )
465+ }
453466 }
454467 }
455468
@@ -473,9 +486,17 @@ if cfg!(target_endian = \"little\") {
473486$EndFeature, "
474487```" ) ,
475488 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
489+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
476490 #[ inline]
477- pub fn from_le( x: Self ) -> Self {
478- if cfg!( target_endian = "little" ) { x } else { x. swap_bytes( ) }
491+ pub const fn from_le( x: Self ) -> Self {
492+ #[ cfg( target_endian = "little" ) ]
493+ {
494+ x
495+ }
496+ #[ cfg( not( target_endian = "little" ) ) ]
497+ {
498+ x. swap_bytes( )
499+ }
479500 }
480501 }
481502
@@ -499,9 +520,17 @@ if cfg!(target_endian = \"big\") {
499520$EndFeature, "
500521```" ) ,
501522 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
523+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
502524 #[ inline]
503- pub fn to_be( self ) -> Self { // or not to be?
504- if cfg!( target_endian = "big" ) { self } else { self . swap_bytes( ) }
525+ pub const fn to_be( self ) -> Self { // or not to be?
526+ #[ cfg( target_endian = "big" ) ]
527+ {
528+ self
529+ }
530+ #[ cfg( not( target_endian = "big" ) ) ]
531+ {
532+ self . swap_bytes( )
533+ }
505534 }
506535 }
507536
@@ -525,9 +554,17 @@ if cfg!(target_endian = \"little\") {
525554$EndFeature, "
526555```" ) ,
527556 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
557+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
528558 #[ inline]
529- pub fn to_le( self ) -> Self {
530- if cfg!( target_endian = "little" ) { self } else { self . swap_bytes( ) }
559+ pub const fn to_le( self ) -> Self {
560+ #[ cfg( target_endian = "little" ) ]
561+ {
562+ self
563+ }
564+ #[ cfg( not( target_endian = "little" ) ) ]
565+ {
566+ self . swap_bytes( )
567+ }
531568 }
532569 }
533570
@@ -1943,6 +1980,19 @@ impl isize {
19431980 int_impl ! { isize , i64 , u64 , 64 , -9223372036854775808 , 9223372036854775807 , "" , "" }
19441981}
19451982
1983+ // Emits the correct `cttz` call, depending on the size of the type.
1984+ macro_rules! uint_cttz_call {
1985+ // As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
1986+ // emits two conditional moves on x86_64. By promoting the value to
1987+ // u16 and setting bit 8, we get better code without any conditional
1988+ // operations.
1989+ // FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
1990+ // pending, remove this workaround once LLVM generates better code
1991+ // for cttz8.
1992+ ( $value: expr, 8 ) => { intrinsics:: cttz( $value as u16 | 0x100 ) } ;
1993+ ( $value: expr, $_BITS: expr) => { intrinsics:: cttz( $value) }
1994+ }
1995+
19461996// `Int` + `UnsignedInt` implemented for unsigned integers
19471997macro_rules! uint_impl {
19481998 ( $SelfT: ty, $ActualT: ty, $BITS: expr, $MaxV: expr, $Feature: expr, $EndFeature: expr) => {
@@ -2020,8 +2070,9 @@ Basic usage:
20202070assert_eq!(n.count_ones(), 3);" , $EndFeature, "
20212071```" ) ,
20222072 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2073+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
20232074 #[ inline]
2024- pub fn count_ones( self ) -> u32 {
2075+ pub const fn count_ones( self ) -> u32 {
20252076 unsafe { intrinsics:: ctpop( self as $ActualT) as u32 }
20262077 }
20272078 }
@@ -2037,8 +2088,9 @@ Basic usage:
20372088" , $Feature, "assert_eq!(" , stringify!( $SelfT) , "::max_value().count_zeros(), 0);" , $EndFeature, "
20382089```" ) ,
20392090 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2091+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
20402092 #[ inline]
2041- pub fn count_zeros( self ) -> u32 {
2093+ pub const fn count_zeros( self ) -> u32 {
20422094 ( !self ) . count_ones( )
20432095 }
20442096 }
@@ -2056,8 +2108,9 @@ Basic usage:
20562108assert_eq!(n.leading_zeros(), 2);" , $EndFeature, "
20572109```" ) ,
20582110 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2111+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
20592112 #[ inline]
2060- pub fn leading_zeros( self ) -> u32 {
2113+ pub const fn leading_zeros( self ) -> u32 {
20612114 unsafe { intrinsics:: ctlz( self as $ActualT) as u32 }
20622115 }
20632116 }
@@ -2076,22 +2129,10 @@ Basic usage:
20762129assert_eq!(n.trailing_zeros(), 3);" , $EndFeature, "
20772130```" ) ,
20782131 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2132+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
20792133 #[ inline]
2080- pub fn trailing_zeros( self ) -> u32 {
2081- // As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
2082- // emits two conditional moves on x86_64. By promoting the value to
2083- // u16 and setting bit 8, we get better code without any conditional
2084- // operations.
2085- // FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
2086- // pending, remove this workaround once LLVM generates better code
2087- // for cttz8.
2088- unsafe {
2089- if $BITS == 8 {
2090- intrinsics:: cttz( self as u16 | 0x100 ) as u32
2091- } else {
2092- intrinsics:: cttz( self ) as u32
2093- }
2094- }
2134+ pub const fn trailing_zeros( self ) -> u32 {
2135+ unsafe { uint_cttz_call!( self , $BITS) as u32 }
20952136 }
20962137 }
20972138
@@ -2167,8 +2208,9 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
21672208 /// assert_eq!(m, 21760);
21682209 /// ```
21692210 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2211+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
21702212 #[ inline]
2171- pub fn swap_bytes( self ) -> Self {
2213+ pub const fn swap_bytes( self ) -> Self {
21722214 unsafe { intrinsics:: bswap( self as $ActualT) as Self }
21732215 }
21742216
@@ -2218,9 +2260,17 @@ if cfg!(target_endian = \"big\") {
22182260}" , $EndFeature, "
22192261```" ) ,
22202262 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2263+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
22212264 #[ inline]
2222- pub fn from_be( x: Self ) -> Self {
2223- if cfg!( target_endian = "big" ) { x } else { x. swap_bytes( ) }
2265+ pub const fn from_be( x: Self ) -> Self {
2266+ #[ cfg( target_endian = "big" ) ]
2267+ {
2268+ x
2269+ }
2270+ #[ cfg( not( target_endian = "big" ) ) ]
2271+ {
2272+ x. swap_bytes( )
2273+ }
22242274 }
22252275 }
22262276
@@ -2244,9 +2294,17 @@ if cfg!(target_endian = \"little\") {
22442294}" , $EndFeature, "
22452295```" ) ,
22462296 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2297+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
22472298 #[ inline]
2248- pub fn from_le( x: Self ) -> Self {
2249- if cfg!( target_endian = "little" ) { x } else { x. swap_bytes( ) }
2299+ pub const fn from_le( x: Self ) -> Self {
2300+ #[ cfg( target_endian = "little" ) ]
2301+ {
2302+ x
2303+ }
2304+ #[ cfg( not( target_endian = "little" ) ) ]
2305+ {
2306+ x. swap_bytes( )
2307+ }
22502308 }
22512309 }
22522310
@@ -2270,9 +2328,17 @@ if cfg!(target_endian = \"big\") {
22702328}" , $EndFeature, "
22712329```" ) ,
22722330 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2331+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
22732332 #[ inline]
2274- pub fn to_be( self ) -> Self { // or not to be?
2275- if cfg!( target_endian = "big" ) { self } else { self . swap_bytes( ) }
2333+ pub const fn to_be( self ) -> Self { // or not to be?
2334+ #[ cfg( target_endian = "big" ) ]
2335+ {
2336+ self
2337+ }
2338+ #[ cfg( not( target_endian = "big" ) ) ]
2339+ {
2340+ self . swap_bytes( )
2341+ }
22762342 }
22772343 }
22782344
@@ -2296,9 +2362,17 @@ if cfg!(target_endian = \"little\") {
22962362}" , $EndFeature, "
22972363```" ) ,
22982364 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
2365+ #[ rustc_const_unstable( feature = "const_int_ops" ) ]
22992366 #[ inline]
2300- pub fn to_le( self ) -> Self {
2301- if cfg!( target_endian = "little" ) { self } else { self . swap_bytes( ) }
2367+ pub const fn to_le( self ) -> Self {
2368+ #[ cfg( target_endian = "little" ) ]
2369+ {
2370+ self
2371+ }
2372+ #[ cfg( not( target_endian = "little" ) ) ]
2373+ {
2374+ self . swap_bytes( )
2375+ }
23022376 }
23032377 }
23042378
0 commit comments