@@ -29,6 +29,20 @@ const NANOS_PER_MICRO: u32 = 1_000;
2929const  MILLIS_PER_SEC :  u64  = 1_000 ; 
3030const  MICROS_PER_SEC :  u64  = 1_000_000 ; 
3131
32+ #[ derive( Clone ,  Copy ,  PartialEq ,  Eq ,  PartialOrd ,  Ord ,  Hash ) ]  
33+ #[ repr( transparent) ]  
34+ #[ rustc_layout_scalar_valid_range_start( 0 ) ]  
35+ #[ rustc_layout_scalar_valid_range_end( 999_999_999 ) ]  
36+ struct  Nanoseconds ( u32 ) ; 
37+ 
38+ impl  Default  for  Nanoseconds  { 
39+  #[ inline]  
40+  fn  default ( )  -> Self  { 
41+  // SAFETY: 0 is within the valid range 
42+  unsafe  {  Nanoseconds ( 0 )  } 
43+  } 
44+ } 
45+ 
3246/// A `Duration` type to represent a span of time, typically used for system 
3347/// timeouts. 
3448/// 
@@ -71,7 +85,7 @@ const MICROS_PER_SEC: u64 = 1_000_000;
7185#[ cfg_attr( not( test) ,  rustc_diagnostic_item = "Duration" ) ]  
7286pub  struct  Duration  { 
7387 secs :  u64 , 
74-  nanos :  u32 ,  // Always 0 <= nanos < NANOS_PER_SEC 
88+  nanos :  Nanoseconds ,  // Always 0 <= nanos < NANOS_PER_SEC 
7589} 
7690
7791impl  Duration  { 
@@ -188,7 +202,8 @@ impl Duration {
188202 None  => panic ! ( "overflow in Duration::new" ) , 
189203 } ; 
190204 let  nanos = nanos % NANOS_PER_SEC ; 
191-  Duration  {  secs,  nanos } 
205+  // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range 
206+  Duration  {  secs,  nanos :  unsafe  {  Nanoseconds ( nanos)  }  } 
192207 } 
193208
194209 /// Creates a new `Duration` from the specified number of whole seconds. 
@@ -208,7 +223,7 @@ impl Duration {
208223 #[ inline]  
209224 #[ rustc_const_stable( feature = "duration_consts" ,  since = "1.32.0" ) ]  
210225 pub  const  fn  from_secs ( secs :  u64 )  -> Duration  { 
211-  Duration   {   secs,  nanos :   0   } 
226+  Duration :: new ( secs,  0 ) 
212227 } 
213228
214229 /// Creates a new `Duration` from the specified number of milliseconds. 
@@ -228,10 +243,7 @@ impl Duration {
228243 #[ inline]  
229244 #[ rustc_const_stable( feature = "duration_consts" ,  since = "1.32.0" ) ]  
230245 pub  const  fn  from_millis ( millis :  u64 )  -> Duration  { 
231-  Duration  { 
232-  secs :  millis / MILLIS_PER_SEC , 
233-  nanos :  ( ( millis % MILLIS_PER_SEC )  as  u32 )  *  NANOS_PER_MILLI , 
234-  } 
246+  Duration :: new ( millis / MILLIS_PER_SEC ,  ( ( millis % MILLIS_PER_SEC )  as  u32 )  *  NANOS_PER_MILLI ) 
235247 } 
236248
237249 /// Creates a new `Duration` from the specified number of microseconds. 
@@ -251,10 +263,7 @@ impl Duration {
251263 #[ inline]  
252264 #[ rustc_const_stable( feature = "duration_consts" ,  since = "1.32.0" ) ]  
253265 pub  const  fn  from_micros ( micros :  u64 )  -> Duration  { 
254-  Duration  { 
255-  secs :  micros / MICROS_PER_SEC , 
256-  nanos :  ( ( micros % MICROS_PER_SEC )  as  u32 )  *  NANOS_PER_MICRO , 
257-  } 
266+  Duration :: new ( micros / MICROS_PER_SEC ,  ( ( micros % MICROS_PER_SEC )  as  u32 )  *  NANOS_PER_MICRO ) 
258267 } 
259268
260269 /// Creates a new `Duration` from the specified number of nanoseconds. 
@@ -274,10 +283,7 @@ impl Duration {
274283 #[ inline]  
275284 #[ rustc_const_stable( feature = "duration_consts" ,  since = "1.32.0" ) ]  
276285 pub  const  fn  from_nanos ( nanos :  u64 )  -> Duration  { 
277-  Duration  { 
278-  secs :  nanos / ( NANOS_PER_SEC  as  u64 ) , 
279-  nanos :  ( nanos % ( NANOS_PER_SEC  as  u64 ) )  as  u32 , 
280-  } 
286+  Duration :: new ( nanos / ( NANOS_PER_SEC  as  u64 ) ,  ( nanos % ( NANOS_PER_SEC  as  u64 ) )  as  u32 ) 
281287 } 
282288
283289 /// Returns true if this `Duration` spans no time. 
@@ -301,7 +307,7 @@ impl Duration {
301307 #[ rustc_const_stable( feature = "duration_zero" ,  since = "1.53.0" ) ]  
302308 #[ inline]  
303309 pub  const  fn  is_zero ( & self )  -> bool  { 
304-  self . secs  == 0  && self . nanos  == 0 
310+  self . secs  == 0  && self . nanos . 0  == 0 
305311 } 
306312
307313 /// Returns the number of _whole_ seconds contained by this `Duration`. 
@@ -352,7 +358,7 @@ impl Duration {
352358 #[ must_use]  
353359 #[ inline]  
354360 pub  const  fn  subsec_millis ( & self )  -> u32  { 
355-  self . nanos  / NANOS_PER_MILLI 
361+  self . nanos . 0  / NANOS_PER_MILLI 
356362 } 
357363
358364 /// Returns the fractional part of this `Duration`, in whole microseconds. 
@@ -375,7 +381,7 @@ impl Duration {
375381 #[ must_use]  
376382 #[ inline]  
377383 pub  const  fn  subsec_micros ( & self )  -> u32  { 
378-  self . nanos  / NANOS_PER_MICRO 
384+  self . nanos . 0  / NANOS_PER_MICRO 
379385 } 
380386
381387 /// Returns the fractional part of this `Duration`, in nanoseconds. 
@@ -398,7 +404,7 @@ impl Duration {
398404 #[ must_use]  
399405 #[ inline]  
400406 pub  const  fn  subsec_nanos ( & self )  -> u32  { 
401-  self . nanos 
407+  self . nanos . 0 
402408 } 
403409
404410 /// Returns the total number of whole milliseconds contained by this `Duration`. 
@@ -416,7 +422,7 @@ impl Duration {
416422 #[ must_use]  
417423 #[ inline]  
418424 pub  const  fn  as_millis ( & self )  -> u128  { 
419-  self . secs  as  u128  *  MILLIS_PER_SEC  as  u128  + ( self . nanos  / NANOS_PER_MILLI )  as  u128 
425+  self . secs  as  u128  *  MILLIS_PER_SEC  as  u128  + ( self . nanos . 0  / NANOS_PER_MILLI )  as  u128 
420426 } 
421427
422428 /// Returns the total number of whole microseconds contained by this `Duration`. 
@@ -434,7 +440,7 @@ impl Duration {
434440 #[ must_use]  
435441 #[ inline]  
436442 pub  const  fn  as_micros ( & self )  -> u128  { 
437-  self . secs  as  u128  *  MICROS_PER_SEC  as  u128  + ( self . nanos  / NANOS_PER_MICRO )  as  u128 
443+  self . secs  as  u128  *  MICROS_PER_SEC  as  u128  + ( self . nanos . 0  / NANOS_PER_MICRO )  as  u128 
438444 } 
439445
440446 /// Returns the total number of nanoseconds contained by this `Duration`. 
@@ -452,7 +458,7 @@ impl Duration {
452458 #[ must_use]  
453459 #[ inline]  
454460 pub  const  fn  as_nanos ( & self )  -> u128  { 
455-  self . secs  as  u128  *  NANOS_PER_SEC  as  u128  + self . nanos  as  u128 
461+  self . secs  as  u128  *  NANOS_PER_SEC  as  u128  + self . nanos . 0  as  u128 
456462 } 
457463
458464 /// Checked `Duration` addition. Computes `self + other`, returning [`None`] 
@@ -475,7 +481,7 @@ impl Duration {
475481 #[ rustc_const_stable( feature = "duration_consts_2" ,  since = "1.58.0" ) ]  
476482 pub  const  fn  checked_add ( self ,  rhs :  Duration )  -> Option < Duration >  { 
477483 if  let  Some ( mut  secs)  = self . secs . checked_add ( rhs. secs )  { 
478-  let  mut  nanos = self . nanos  + rhs. nanos ; 
484+  let  mut  nanos = self . nanos . 0  + rhs. nanos . 0 ; 
479485 if  nanos >= NANOS_PER_SEC  { 
480486 nanos -= NANOS_PER_SEC ; 
481487 if  let  Some ( new_secs)  = secs. checked_add ( 1 )  { 
@@ -485,7 +491,7 @@ impl Duration {
485491 } 
486492 } 
487493 debug_assert ! ( nanos < NANOS_PER_SEC ) ; 
488-  Some ( Duration   {   secs,  nanos  } ) 
494+  Some ( Duration :: new ( secs,  nanos) ) 
489495 }  else  { 
490496 None 
491497 } 
@@ -535,16 +541,16 @@ impl Duration {
535541 #[ rustc_const_stable( feature = "duration_consts_2" ,  since = "1.58.0" ) ]  
536542 pub  const  fn  checked_sub ( self ,  rhs :  Duration )  -> Option < Duration >  { 
537543 if  let  Some ( mut  secs)  = self . secs . checked_sub ( rhs. secs )  { 
538-  let  nanos = if  self . nanos  >= rhs. nanos  { 
539-  self . nanos  - rhs. nanos 
544+  let  nanos = if  self . nanos . 0  >= rhs. nanos . 0  { 
545+  self . nanos . 0  - rhs. nanos . 0 
540546 }  else  if  let  Some ( sub_secs)  = secs. checked_sub ( 1 )  { 
541547 secs = sub_secs; 
542-  self . nanos  + NANOS_PER_SEC  - rhs. nanos 
548+  self . nanos . 0  + NANOS_PER_SEC  - rhs. nanos . 0 
543549 }  else  { 
544550 return  None ; 
545551 } ; 
546552 debug_assert ! ( nanos < NANOS_PER_SEC ) ; 
547-  Some ( Duration   {   secs,  nanos  } ) 
553+  Some ( Duration :: new ( secs,  nanos) ) 
548554 }  else  { 
549555 None 
550556 } 
@@ -593,13 +599,13 @@ impl Duration {
593599 #[ rustc_const_stable( feature = "duration_consts_2" ,  since = "1.58.0" ) ]  
594600 pub  const  fn  checked_mul ( self ,  rhs :  u32 )  -> Option < Duration >  { 
595601 // Multiply nanoseconds as u64, because it cannot overflow that way. 
596-  let  total_nanos = self . nanos  as  u64  *  rhs as  u64 ; 
602+  let  total_nanos = self . nanos . 0  as  u64  *  rhs as  u64 ; 
597603 let  extra_secs = total_nanos / ( NANOS_PER_SEC  as  u64 ) ; 
598604 let  nanos = ( total_nanos % ( NANOS_PER_SEC  as  u64 ) )  as  u32 ; 
599605 if  let  Some ( s)  = self . secs . checked_mul ( rhs as  u64 )  { 
600606 if  let  Some ( secs)  = s. checked_add ( extra_secs)  { 
601607 debug_assert ! ( nanos < NANOS_PER_SEC ) ; 
602-  return  Some ( Duration   {   secs,  nanos  } ) ; 
608+  return  Some ( Duration :: new ( secs,  nanos) ) ; 
603609 } 
604610 } 
605611 None 
@@ -653,9 +659,9 @@ impl Duration {
653659 let  secs = self . secs  / ( rhs as  u64 ) ; 
654660 let  carry = self . secs  - secs *  ( rhs as  u64 ) ; 
655661 let  extra_nanos = carry *  ( NANOS_PER_SEC  as  u64 )  / ( rhs as  u64 ) ; 
656-  let  nanos = self . nanos  / rhs + ( extra_nanos as  u32 ) ; 
662+  let  nanos = self . nanos . 0  / rhs + ( extra_nanos as  u32 ) ; 
657663 debug_assert ! ( nanos < NANOS_PER_SEC ) ; 
658-  Some ( Duration   {   secs,  nanos  } ) 
664+  Some ( Duration :: new ( secs,  nanos) ) 
659665 }  else  { 
660666 None 
661667 } 
@@ -677,7 +683,7 @@ impl Duration {
677683 #[ inline]  
678684 #[ rustc_const_unstable( feature = "duration_consts_float" ,  issue = "72440" ) ]  
679685 pub  const  fn  as_secs_f64 ( & self )  -> f64  { 
680-  ( self . secs  as  f64 )  + ( self . nanos  as  f64 )  / ( NANOS_PER_SEC  as  f64 ) 
686+  ( self . secs  as  f64 )  + ( self . nanos . 0  as  f64 )  / ( NANOS_PER_SEC  as  f64 ) 
681687 } 
682688
683689 /// Returns the number of seconds contained by this `Duration` as `f32`. 
@@ -696,7 +702,7 @@ impl Duration {
696702 #[ inline]  
697703 #[ rustc_const_unstable( feature = "duration_consts_float" ,  issue = "72440" ) ]  
698704 pub  const  fn  as_secs_f32 ( & self )  -> f32  { 
699-  ( self . secs  as  f32 )  + ( self . nanos  as  f32 )  / ( NANOS_PER_SEC  as  f32 ) 
705+  ( self . secs  as  f32 )  + ( self . nanos . 0  as  f32 )  / ( NANOS_PER_SEC  as  f32 ) 
700706 } 
701707
702708 /// Creates a new `Duration` from the specified number of seconds represented 
@@ -987,21 +993,21 @@ macro_rules! sum_durations {
987993 for  entry in $iter { 
988994 total_secs =
989995 total_secs. checked_add( entry. secs) . expect( "overflow in iter::sum over durations" ) ; 
990-  total_nanos = match  total_nanos. checked_add( entry. nanos as  u64 )  { 
996+  total_nanos = match  total_nanos. checked_add( entry. nanos. 0  as  u64 )  { 
991997 Some ( n)  => n, 
992998 None  => { 
993999 total_secs = total_secs
9941000 . checked_add( total_nanos / NANOS_PER_SEC  as  u64 ) 
9951001 . expect( "overflow in iter::sum over durations" ) ; 
996-  ( total_nanos % NANOS_PER_SEC  as  u64 )  + entry. nanos as  u64 
1002+  ( total_nanos % NANOS_PER_SEC  as  u64 )  + entry. nanos. 0  as  u64 
9971003 } 
9981004 } ; 
9991005 } 
10001006 total_secs = total_secs
10011007 . checked_add( total_nanos / NANOS_PER_SEC  as  u64 ) 
10021008 . expect( "overflow in iter::sum over durations" ) ; 
10031009 total_nanos = total_nanos % NANOS_PER_SEC  as  u64 ; 
1004-  Duration   {  secs :   total_secs,  nanos :   total_nanos as  u32   } 
1010+  Duration :: new ( total_secs,  total_nanos as  u32 ) 
10051011 } } ; 
10061012} 
10071013
@@ -1166,27 +1172,27 @@ impl fmt::Debug for Duration {
11661172 let  prefix = if  f. sign_plus ( )  {  "+"  }  else  {  ""  } ; 
11671173
11681174 if  self . secs  > 0  { 
1169-  fmt_decimal ( f,  self . secs ,  self . nanos ,  NANOS_PER_SEC  / 10 ,  prefix,  "s" ) 
1170-  }  else  if  self . nanos  >= NANOS_PER_MILLI  { 
1175+  fmt_decimal ( f,  self . secs ,  self . nanos . 0 ,  NANOS_PER_SEC  / 10 ,  prefix,  "s" ) 
1176+  }  else  if  self . nanos . 0  >= NANOS_PER_MILLI  { 
11711177 fmt_decimal ( 
11721178 f, 
1173-  ( self . nanos  / NANOS_PER_MILLI )  as  u64 , 
1174-  self . nanos  % NANOS_PER_MILLI , 
1179+  ( self . nanos . 0  / NANOS_PER_MILLI )  as  u64 , 
1180+  self . nanos . 0  % NANOS_PER_MILLI , 
11751181 NANOS_PER_MILLI  / 10 , 
11761182 prefix, 
11771183 "ms" , 
11781184 ) 
1179-  }  else  if  self . nanos  >= NANOS_PER_MICRO  { 
1185+  }  else  if  self . nanos . 0  >= NANOS_PER_MICRO  { 
11801186 fmt_decimal ( 
11811187 f, 
1182-  ( self . nanos  / NANOS_PER_MICRO )  as  u64 , 
1183-  self . nanos  % NANOS_PER_MICRO , 
1188+  ( self . nanos . 0  / NANOS_PER_MICRO )  as  u64 , 
1189+  self . nanos . 0  % NANOS_PER_MICRO , 
11841190 NANOS_PER_MICRO  / 10 , 
11851191 prefix, 
11861192 "µs" , 
11871193 ) 
11881194 }  else  { 
1189-  fmt_decimal ( f,  self . nanos  as  u64 ,  0 ,  1 ,  prefix,  "ns" ) 
1195+  fmt_decimal ( f,  self . nanos . 0  as  u64 ,  0 ,  1 ,  prefix,  "ns" ) 
11901196 } 
11911197 } 
11921198} 
@@ -1317,7 +1323,7 @@ macro_rules! try_from_secs {
13171323 return  Err ( FromFloatSecsError  {  kind:  FromFloatSecsErrorKind :: OverflowOrNan  } ) ; 
13181324 } ; 
13191325
1320-  Ok ( Duration   {   secs,  nanos  } ) 
1326+  Ok ( Duration :: new ( secs,  nanos) ) 
13211327 } } ; 
13221328} 
13231329
0 commit comments