Auto merge of #58389 - Centril:rollup, r=Centril

Rollup of 11 pull requests

Successful merges:

 - #58105 (libarena => 2018)
 - #58111 (libterm => 2018)
 - #58287 (rustc-std-workspace-core => 2018)
 - #58288 (rustc-workspace-hack => 2018)
 - #58300 (librustc_typeck => 2018)
 - #58313 (Use `?` in librustc macros)
 - #58318 (libserialize => 2018)
 - #58322 (librustc_codegen_ssa => 2018)
 - #58342 (Revert removed #![feature(nll)])
 - #58367 (Remove two dead functions.)
 - #58382 (docs: remove "experimental" wording from std::os::unix)

Failed merges:

r? @ghost
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index f80f839..d34173d 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -882,17 +882,38 @@
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[inline]
+            #[cfg(stage0)]
             pub fn saturating_add(self, rhs: Self) -> Self {
-                #[cfg(stage0)]
                 match self.checked_add(rhs) {
                     Some(x) => x,
                     None if rhs >= 0 => Self::max_value(),
                     None => Self::min_value(),
                 }
-                #[cfg(not(stage0))]
-                {
-                    intrinsics::saturating_add(self, rhs)
-                }
+            }
+
+        }
+
+        doc_comment! {
+            concat!("Saturating integer addition. Computes `self + rhs`, saturating at the numeric
+bounds instead of overflowing.
+
+# Examples
+
+Basic usage:
+
+```
+", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
+assert_eq!(", stringify!($SelfT), "::max_value().saturating_add(100), ", stringify!($SelfT),
+"::max_value());",
+$EndFeature, "
+```"),
+
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn saturating_add(self, rhs: Self) -> Self {
+                intrinsics::saturating_add(self, rhs)
             }
         }
 
@@ -912,17 +933,36 @@
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[inline]
+            #[cfg(stage0)]
             pub fn saturating_sub(self, rhs: Self) -> Self {
-                #[cfg(stage0)]
                 match self.checked_sub(rhs) {
                     Some(x) => x,
                     None if rhs >= 0 => Self::min_value(),
                     None => Self::max_value(),
                 }
-                #[cfg(not(stage0))]
-                {
-                    intrinsics::saturating_sub(self, rhs)
-                }
+            }
+        }
+
+        doc_comment! {
+            concat!("Saturating integer subtraction. Computes `self - rhs`, saturating at the
+numeric bounds instead of overflowing.
+
+# Examples
+
+Basic usage:
+
+```
+", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27);
+assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringify!($SelfT),
+"::min_value());",
+$EndFeature, "
+```"),
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn saturating_sub(self, rhs: Self) -> Self {
+                intrinsics::saturating_sub(self, rhs)
             }
         }
 
@@ -2753,16 +2793,34 @@
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[inline]
+            #[cfg(stage0)]
             pub fn saturating_add(self, rhs: Self) -> Self {
-                #[cfg(stage0)]
                 match self.checked_add(rhs) {
                     Some(x) => x,
                     None => Self::max_value(),
                 }
-                #[cfg(not(stage0))]
-                {
-                    intrinsics::saturating_add(self, rhs)
-                }
+            }
+        }
+
+        doc_comment! {
+            concat!("Saturating integer addition. Computes `self + rhs`, saturating at
+the numeric bounds instead of overflowing.
+
+# Examples
+
+Basic usage:
+
+```
+", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
+assert_eq!(200u8.saturating_add(127), 255);", $EndFeature, "
+```"),
+
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn saturating_add(self, rhs: Self) -> Self {
+                intrinsics::saturating_add(self, rhs)
             }
         }
 
@@ -2780,16 +2838,33 @@
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
             #[inline]
+            #[cfg(stage0)]
             pub fn saturating_sub(self, rhs: Self) -> Self {
-                #[cfg(stage0)]
                 match self.checked_sub(rhs) {
                     Some(x) => x,
                     None => Self::min_value(),
                 }
-                #[cfg(not(stage0))]
-                {
-                    intrinsics::saturating_sub(self, rhs)
-                }
+            }
+        }
+
+        doc_comment! {
+            concat!("Saturating integer subtraction. Computes `self - rhs`, saturating
+at the numeric bounds instead of overflowing.
+
+# Examples
+
+Basic usage:
+
+```
+", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73);
+assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);", $EndFeature, "
+```"),
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_saturating_int_methods")]
+            #[inline]
+            #[cfg(not(stage0))]
+            pub const fn saturating_sub(self, rhs: Self) -> Self {
+                intrinsics::saturating_sub(self, rhs)
             }
         }
 
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index d8778df..dcbf6a5 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -4,7 +4,7 @@
 
 use syntax::symbol::Symbol;
 use rustc::ty;
-use rustc::ty::layout::{LayoutOf, Primitive};
+use rustc::ty::layout::{LayoutOf, Primitive, Size};
 use rustc::mir::BinOp;
 use rustc::mir::interpret::{
     EvalResult, EvalErrorKind, Scalar,
@@ -122,6 +122,49 @@
                     self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
                 }
             }
+            "saturating_add" | "saturating_sub" => {
+                let l = self.read_immediate(args[0])?;
+                let r = self.read_immediate(args[1])?;
+                let is_add = intrinsic_name == "saturating_add";
+                let (val, overflowed) = self.binary_op_imm(if is_add {
+                    BinOp::Add
+                } else {
+                    BinOp::Sub
+                }, l, r)?;
+                let val = if overflowed {
+                    let num_bits = l.layout.size.bits();
+                    if l.layout.abi.is_signed() {
+                        // For signed ints the saturated value depends on the sign of the first
+                        // term since the sign of the second term can be inferred from this and
+                        // the fact that the operation has overflowed (if either is 0 no
+                        // overflow can occur)
+                        let first_term: u128 = l.to_scalar()?.to_bits(l.layout.size)?;
+                        let first_term_positive = first_term & (1 << (num_bits-1)) == 0;
+                        if first_term_positive {
+                            // Negative overflow not possible since the positive first term
+                            // can only increase an (in range) negative term for addition
+                            // or corresponding negated positive term for subtraction
+                            Scalar::from_uint((1u128 << (num_bits - 1)) - 1,  // max positive
+                                Size::from_bits(num_bits))
+                        } else {
+                            // Positive overflow not possible for similar reason
+                            // max negative
+                            Scalar::from_uint(1u128 << (num_bits - 1), Size::from_bits(num_bits))
+                        }
+                    } else {  // unsigned
+                        if is_add {
+                            // max unsigned
+                            Scalar::from_uint(u128::max_value() >> (128 - num_bits),
+                                Size::from_bits(num_bits))
+                        } else {  // underflow to 0
+                            Scalar::from_uint(0u128, Size::from_bits(num_bits))
+                        }
+                    }
+                } else {
+                    val
+                };
+                self.write_scalar(val, dest)?;
+            }
             "unchecked_shl" | "unchecked_shr" => {
                 let l = self.read_immediate(args[0])?;
                 let r = self.read_immediate(args[1])?;
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 76b8b83..b116c32 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -836,6 +836,8 @@
                                 | "add_with_overflow"
                                 | "sub_with_overflow"
                                 | "mul_with_overflow"
+                                | "saturating_add"
+                                | "saturating_sub"
                                 // no need to check feature gates, intrinsics are only callable
                                 // from the libstd or with forever unstable feature gates
                                 => is_const_fn = true,
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 85bf1e7..d8dc6c2 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -374,6 +374,8 @@
         | "overflowing_add" // ~> .wrapping_add
         | "overflowing_sub" // ~> .wrapping_sub
         | "overflowing_mul" // ~> .wrapping_mul
+        | "saturating_add" // ~> .saturating_add
+        | "saturating_sub" // ~> .saturating_sub
         | "unchecked_shl" // ~> .wrapping_shl
         | "unchecked_shr" // ~> .wrapping_shr
         | "rotate_left" // ~> .rotate_left
diff --git a/src/test/run-pass/const-int-saturating-arith.rs b/src/test/run-pass/const-int-saturating-arith.rs
new file mode 100644
index 0000000..dae4c72
--- /dev/null
+++ b/src/test/run-pass/const-int-saturating-arith.rs
@@ -0,0 +1,34 @@
+// ignore-emscripten no i128 support
+#![feature(const_saturating_int_methods)]
+
+const INT_U32_NO: u32 = (42 as u32).saturating_add(2);
+const INT_U32: u32 = u32::max_value().saturating_add(1);
+const INT_U128: u128 = u128::max_value().saturating_add(1);
+const INT_I128: i128 = i128::max_value().saturating_add(1);
+const INT_I128_NEG: i128 = i128::min_value().saturating_add(-1);
+
+const INT_U32_NO_SUB: u32 = (42 as u32).saturating_sub(2);
+const INT_U32_SUB: u32 = (1 as u32).saturating_sub(2);
+const INT_I32_NO_SUB: i32 = (-42 as i32).saturating_sub(2);
+const INT_I32_NEG_SUB: i32 = i32::min_value().saturating_sub(1);
+const INT_I32_POS_SUB: i32 = i32::max_value().saturating_sub(-1);
+const INT_U128_SUB: u128 = (0 as u128).saturating_sub(1);
+const INT_I128_NEG_SUB: i128 = i128::min_value().saturating_sub(1);
+const INT_I128_POS_SUB: i128 = i128::max_value().saturating_sub(-1);
+
+fn main() {
+    assert_eq!(INT_U32_NO, 44);
+    assert_eq!(INT_U32, u32::max_value());
+    assert_eq!(INT_U128, u128::max_value());
+    assert_eq!(INT_I128, i128::max_value());
+    assert_eq!(INT_I128_NEG, i128::min_value());
+
+    assert_eq!(INT_U32_NO_SUB, 40);
+    assert_eq!(INT_U32_SUB, 0);
+    assert_eq!(INT_I32_NO_SUB, -44);
+    assert_eq!(INT_I32_NEG_SUB, i32::min_value());
+    assert_eq!(INT_I32_POS_SUB, i32::max_value());
+    assert_eq!(INT_U128_SUB, 0);
+    assert_eq!(INT_I128_NEG_SUB, i128::min_value());
+    assert_eq!(INT_I128_POS_SUB, i128::max_value());
+}