@@ -1043,7 +1043,7 @@ impl fmt::Debug for Duration {
10431043 /// to the formatter's `width`, if specified.
10441044 fn fmt_decimal (
10451045 f : & mut fmt:: Formatter < ' _ > ,
1046- mut integer_part : u64 ,
1046+ integer_part : u64 ,
10471047 mut fractional_part : u32 ,
10481048 mut divisor : u32 ,
10491049 prefix : & str ,
@@ -1075,7 +1075,7 @@ impl fmt::Debug for Duration {
10751075 // normal floating point numbers. However, we only need to do work
10761076 // when rounding up. This happens if the first digit of the
10771077 // remaining ones is >= 5.
1078- if fractional_part > 0 && fractional_part >= divisor * 5 {
1078+ let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 {
10791079 // Round up the number contained in the buffer. We go through
10801080 // the buffer backwards and keep track of the carry.
10811081 let mut rev_pos = pos;
@@ -1099,9 +1099,18 @@ impl fmt::Debug for Duration {
10991099 // the whole buffer to '0's and need to increment the integer
11001100 // part.
11011101 if carry {
1102- integer_part += 1 ;
1102+ // If `integer_part == u64::MAX` and precision < 9, any
1103+ // carry of the overflow during rounding of the
1104+ // `fractional_part` into the `integer_part` will cause the
1105+ // `integer_part` itself to overflow. Avoid this by using an
1106+ // `Option<u64>`, with `None` representing `u64::MAX + 1`.
1107+ integer_part. checked_add ( 1 )
1108+ } else {
1109+ Some ( integer_part)
11031110 }
1104- }
1111+ } else {
1112+ Some ( integer_part)
1113+ } ;
11051114
11061115 // Determine the end of the buffer: if precision is set, we just
11071116 // use as many digits from the buffer (capped to 9). If it isn't
@@ -1111,7 +1120,12 @@ impl fmt::Debug for Duration {
11111120 // This closure emits the formatted duration without emitting any
11121121 // padding (padding is calculated below).
11131122 let emit_without_padding = |f : & mut fmt:: Formatter < ' _ > | {
1114- write ! ( f, "{}{}" , prefix, integer_part) ?;
1123+ if let Some ( integer_part) = integer_part {
1124+ write ! ( f, "{}{}" , prefix, integer_part) ?;
1125+ } else {
1126+ // u64::MAX + 1 == 18446744073709551616
1127+ write ! ( f, "{}18446744073709551616" , prefix) ?;
1128+ }
11151129
11161130 // Write the decimal point and the fractional part (if any).
11171131 if end > 0 {
@@ -1141,12 +1155,17 @@ impl fmt::Debug for Duration {
11411155 // 2. The postfix: can be "µs" so we have to count UTF8 characters.
11421156 let mut actual_w = prefix. len ( ) + postfix. chars ( ) . count ( ) ;
11431157 // 3. The integer part:
1144- if let Some ( log) = integer_part. checked_ilog10 ( ) {
1145- // integer_part is > 0, so has length log10(x)+1
1146- actual_w += 1 + log as usize ;
1158+ if let Some ( integer_part) = integer_part {
1159+ if let Some ( log) = integer_part. checked_ilog10 ( ) {
1160+ // integer_part is > 0, so has length log10(x)+1
1161+ actual_w += 1 + log as usize ;
1162+ } else {
1163+ // integer_part is 0, so has length 1.
1164+ actual_w += 1 ;
1165+ }
11471166 } else {
1148- // integer_part is 0 , so has length 1.
1149- actual_w += 1 ;
1167+ // integer_part is u64::MAX + 1 , so has length 20
1168+ actual_w += 20 ;
11501169 }
11511170 // 4. The fractional part (if any):
11521171 if end > 0 {
0 commit comments