Repository: slog-rs/slog (language: rust)

Issue:
Minimum rust version bump in minor version release is a breaking change


This [commit](https://github.com/slog-rs/slog/commit/77e6f0100497270e6f8ce3fe9e0631ad073f8c2f) bumps the minimum version from 1.15.0 to 1.26.1 which is a breaking change and it breaks [builds](https://travis-ci.org/uuid-rs/uuid/jobs/434905483#L1023)  for us which depend on 1.22.0 rust version. 

One solution i to wrap the u128 support in an optional feature gate.  


Discussion / hints:

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index 23b88217a..944f2fcb8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,15 +3,15 @@ cache:
   - cargo
 rust:
   - stable
-  - 1.26.2
+  - 1.15.1
   - beta
   - nightly
 
 script:
     # `patch` section is recent addition
-  - if [ "$TRAVIS_RUST_VERSION" != "1.26.2" ]; then make all ; fi
-  - if [ "$TRAVIS_RUST_VERSION" == "1.26.2" ]; then make build ; fi
-  - if [ "$TRAVIS_RUST_VERSION" != "1.26.2" ]; then make travistest ; fi
+  - if [ "$TRAVIS_RUST_VERSION" != "1.15.1" ]; then make all ; fi
+  - if [ "$TRAVIS_RUST_VERSION" == "1.15.1" ]; then make build ; fi
+  - if [ "$TRAVIS_RUST_VERSION" != "1.15.1" ]; then make travistest ; fi
   - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then make bench ; fi
   - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo build --no-default-features; cargo test --no-default-features; fi
   - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo test --manifest-path crates/test_edition2018/Cargo.toml; fi
diff --git a/Cargo.toml b/Cargo.toml
index 77c9ee8fe..aeb9e2675 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,6 +11,8 @@ homepage = "https://github.com/slog-rs/slog"
 repository = "https://github.com/slog-rs/slog"
 readme = "README.md"
 
+build = "build.rs"
+
 [profile.release]
 opt-level = 3
 debug = false
diff --git a/build.rs b/build.rs
new file mode 100644
index 000000000..14bf916b8
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,44 @@
+use std::env;
+use std::process::Command;
+use std::str;
+
+// FIXME: replace it with '?' operator
+macro_rules! try_opt {
+    ($e:expr) => {
+        match { $e } {
+            Some(e) => e,
+            None => return None,
+        }
+    };
+}
+
+fn rustc_minor_version() -> Option<u32> {
+    let rustc = try_opt!(env::var_os("RUSTC"));
+    let output = try_opt!(Command::new(rustc).arg("--version").output().ok());
+    let version_str = try_opt!(str::from_utf8(&output.stdout).ok());
+    let minor_str = try_opt!(version_str.split('.').nth(1));
+
+    minor_str.parse().ok()
+}
+
+fn main() {
+    let minor = match rustc_minor_version() {
+        Some(m) => m,
+        None => return,
+    };
+
+    let target = env::var("TARGET").unwrap();
+    let is_emscripten = target == "asmjs-unknown-emscripten"
+        || target == "wasm32-unknown-emscripten";
+
+    if minor >= 26 && !is_emscripten {
+        println!("cargo:rustc-cfg=integer128");
+    }
+
+    // workaround on macro bugs fixed in 1.20
+    //
+    // https://github.com/rust-lang/rust/pull/42913
+    if minor < 20 {
+        println!("cargo:rustc-cfg=macro_workaround");
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 66e7d9527..e368945e7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2412,17 +2412,31 @@ impl<'a> Record<'a> {
 // }}}
 
 // {{{ Serializer
+
+#[cfg(macro_workaround)]
 macro_rules! impl_default_as_fmt{
-    ($(
-        $(#[$m:meta])*
-        $t:ty => $f:ident,
-    )*) => {$(
+    (#[$m:meta] $($t:tt)+) => {
+        #[$m]
+        impl_default_as_fmt!($($t)*);
+    };
+    ($t:ty => $f:ident) => {
+        #[allow(missing_docs)]
+        fn $f(&mut self, key : Key, val : $t)
+            -> Result {
+                self.emit_arguments(key, &format_args!("{}", val))
+            }
+    };
+}
+
+#[cfg(not(macro_workaround))]
+macro_rules! impl_default_as_fmt{
+    ($(#[$m:meta])* $t:ty => $f:ident) => {
         $(#[$m])*
         fn $f(&mut self, key : Key, val : $t)
             -> Result {
                 self.emit_arguments(key, &format_args!("{}", val))
             }
-    )*};
+    };
 }
 
 /// This is a workaround to be able to pass &mut Serializer, from
@@ -2451,39 +2465,73 @@ impl<'a, T: Serializer + 'a + ?Sized> Serializer for SerializerForward<'a, T> {
 pub trait Serializer {
     impl_default_as_fmt! {
         /// Emit `usize`
-        usize => emit_usize,
+        usize => emit_usize
+    }
+    impl_default_as_fmt! {
         /// Emit `isize`
-        isize => emit_isize,
+        isize => emit_isize
+    }
+    impl_default_as_fmt! {
         /// Emit `bool`
-        bool => emit_bool,
+        bool => emit_bool
+    }
+    impl_default_as_fmt! {
         /// Emit `char`
-        char => emit_char,
+        char => emit_char
+    }
+    impl_default_as_fmt! {
         /// Emit `u8`
-        u8 => emit_u8,
+        u8 => emit_u8
+    }
+    impl_default_as_fmt! {
         /// Emit `i8`
-        i8 => emit_i8,
+        i8 => emit_i8
+    }
+    impl_default_as_fmt! {
         /// Emit `u16`
-        u16 => emit_u16,
+        u16 => emit_u16
+    }
+    impl_default_as_fmt! {
         /// Emit `i16`
-        i16 => emit_i16,
+        i16 => emit_i16
+    }
+    impl_default_as_fmt! {
         /// Emit `u32`
-        u32 => emit_u32,
+        u32 => emit_u32
+    }
+    impl_default_as_fmt! {
         /// Emit `i32`
-        i32 => emit_i32,
+        i32 => emit_i32
+    }
+    impl_default_as_fmt! {
         /// Emit `f32`
-        f32 => emit_f32,
+        f32 => emit_f32
+    }
+    impl_default_as_fmt! {
         /// Emit `u64`
-        u64 => emit_u64,
+        u64 => emit_u64
+    }
+    impl_default_as_fmt! {
         /// Emit `i64`
-        i64 => emit_i64,
+        i64 => emit_i64
+    }
+    impl_default_as_fmt! {
         /// Emit `f64`
-        f64 => emit_f64,
+        f64 => emit_f64
+    }
+    impl_default_as_fmt! {
         /// Emit `u128`
-        u128 => emit_u128,
+        #[cfg(integer128)]
+        u128 => emit_u128
+    }
+    impl_default_as_fmt! {
         /// Emit `i128`
-        i128 => emit_i128,
+        #[cfg(integer128)]
+        i128 => emit_i128
+    }
+    impl_default_as_fmt! {
         /// Emit `&str`
-        &str => emit_str,
+        &str => emit_str
     }
 
     /// Emit `()`
@@ -2648,7 +2696,9 @@ impl_value_for!(f32, emit_f32);
 impl_value_for!(u64, emit_u64);
 impl_value_for!(i64, emit_i64);
 impl_value_for!(f64, emit_f64);
+#[cfg(integer128)]
 impl_value_for!(u128, emit_u128);
+#[cfg(integer128)]
 impl_value_for!(i128, emit_i128);
 
 impl Value for () {


Test patch:
diff --git a/src/tests.rs b/src/tests.rs
index 8c4f25608..fcabd1248 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -186,6 +186,15 @@ fn expressions() {
           "aaa" => "bbb");
 }
 
+#[cfg(integer128)]
+#[test]
+fn integer_128_types() {
+    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));
+
+    info!(log, "i128 = {}", 42i128; "foo" => 7i128);
+    info!(log, "u128 = {}", 42u128; "foo" => 7u128);
+}
+
 #[test]
 fn expressions_fmt() {
     let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));