Merge pull request #2273 from allengeorge/allen/clippy_clean

THRIFT-5306: Rust code and generated code no longer has clippy warnings (Rust 1.40)
diff --git a/.gitignore b/.gitignore
index 58e2582..76d9e50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -288,6 +288,7 @@
 /lib/rs/test/src/midlayer.rs
 /lib/rs/test/src/recursive.rs
 /lib/rs/test/src/ultimate.rs
+/lib/rs/test/src/identifiers.rs
 /lib/rs/*.iml
 /lib/rs/**/*.iml
 /lib/swift/.build
diff --git a/LANGUAGES.md b/LANGUAGES.md
index 3173ec3..4ea86f7 100644
--- a/LANGUAGES.md
+++ b/LANGUAGES.md
@@ -314,7 +314,7 @@
 <td align=left><a href="https://github.com/apache/thrift/blob/master/lib/rs/README.md">Rust</a></td>
 <!-- Since -----------------><td>0.11.0</td>
 <!-- Build Systems ---------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
-<!-- Language Levels -------><td>1.35.0</td><td>1.35.0</td>
+<!-- Language Levels -------><td>1.40.0</td><td>1.xx.x</td>
 <!-- Low-Level Transports --><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Transport Wrappers ----><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cred.png" alt=""/></td>
 <!-- Protocols -------------><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td><td><img src="doc/images/cred.png" alt=""/></td><td><img src="doc/images/cgrn.png" alt="Yes"/></td>
diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc
index 506e090..f55b7e0 100644
--- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc
@@ -554,7 +554,6 @@
   f_gen_ << endl;
 
   // add standard includes
-  f_gen_ << "use thrift::OrderedFloat;" << endl;
   f_gen_ << "use std::cell::RefCell;" << endl;
   f_gen_ << "use std::collections::{BTreeMap, BTreeSet};" << endl;
   f_gen_ << "use std::convert::{From, TryFrom};" << endl;
@@ -564,6 +563,7 @@
   f_gen_ << "use std::fmt::{Display, Formatter};" << endl;
   f_gen_ << "use std::rc::Rc;" << endl;
   f_gen_ << endl;
+  f_gen_ << "use thrift::OrderedFloat;" << endl;
   f_gen_ << "use thrift::{ApplicationError, ApplicationErrorKind, ProtocolError, ProtocolErrorKind, TThriftClient};" << endl;
   f_gen_ << "use thrift::protocol::{TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TInputProtocol, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType};" << endl;
   f_gen_ << "use thrift::protocol::field_id;" << endl;
@@ -706,7 +706,7 @@
       f_gen_ << tvalue->get_integer();
       break;
     case t_base_type::TYPE_DOUBLE:
-      f_gen_ << "OrderedFloat::from(" << tvalue->get_double() << " as f64)";
+      f_gen_ << "OrderedFloat::from(" << tvalue->get_double() << "_f64)";
       break;
     default:
       throw "cannot generate const value for " + t_base_type::t_base_name(tbase_type->get_base());
@@ -901,12 +901,16 @@
   f_gen_ << "impl " << enum_name << " {" << endl;
   indent_up();
 
+  // taking enum as 'self' here because Thrift enums
+  // are represented as Rust enums with integer values
+  // it's cheaper to copy the integer as opposed to
+  // taking a reference to the enum
   f_gen_
     << indent()
-    << "pub fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {"
+    << "pub fn write_to_out_protocol(self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {"
     << endl;
   indent_up();
-  f_gen_ << indent() << "o_prot.write_i32(*self as i32)" << endl;
+  f_gen_ << indent() << "o_prot.write_i32(self as i32)" << endl;
   indent_down();
   f_gen_ << indent() << "}" << endl;
 
@@ -1230,7 +1234,7 @@
     << endl;
   indent_up();
 
-  if (members.size() == 0) {
+  if (members.empty()) {
     f_gen_ << indent() << struct_name << " {}" << endl;
   } else {
     f_gen_ << indent() << struct_name << " {" << endl;
@@ -1244,7 +1248,7 @@
       if (is_optional(member_req)) {
         f_gen_ << indent() << member_name << ": " << member_name << ".into()," << endl;
       } else {
-        f_gen_ << indent() << member_name << ": " << member_name << "," << endl;
+        f_gen_ << indent() << member_name << "," << endl;
       }
     }
 
@@ -1504,19 +1508,14 @@
     indent_up();
     f_gen_ << indent() << "o_prot.write_field_begin(&" << field_ident_string << ")?;" << endl;
     render_type_sync_write("fld_var", true, field_type);
-    f_gen_ << indent() << "o_prot.write_field_end()?;" << endl;
-    f_gen_ << indent() << "()" << endl; // FIXME: remove this extraneous '()'
+    f_gen_ << indent() << "o_prot.write_field_end()?" << endl;
     indent_down();
-    f_gen_ << indent() << "} else {" << endl; // FIXME: remove else branch
-    indent_up();
     /* FIXME: rethink how I deal with OPT_IN_REQ_OUT
     if (req == t_field::T_OPT_IN_REQ_OUT) {
       f_gen_ << indent() << "let field_ident = " << field_ident_string << ";" << endl;
       f_gen_ << indent() << "o_prot.write_field_begin(&field_ident)?;" << endl;
       f_gen_ << indent() << "o_prot.write_field_end()?;" << endl;
     }*/
-    f_gen_ << indent() << "()" << endl;
-    indent_down();
     f_gen_ << indent() << "}" << endl;
   } else {
     f_gen_ << indent() << "o_prot.write_field_begin(&" << field_ident_string << ")?;" << endl;
@@ -2308,7 +2307,7 @@
   for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) {
     t_field* member = (*members_iter);
     string member_name(rust_field_name(member));
-    struct_definition << member_name << ": " << member_name << ", ";
+    struct_definition << member_name << ", ";
   }
   string struct_fields = struct_definition.str();
   if (struct_fields.size() > 0) {
diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml
index 674a4c3..182cd8d 100644
--- a/lib/rs/Cargo.toml
+++ b/lib/rs/Cargo.toml
@@ -12,8 +12,8 @@
 keywords = ["thrift"]
 
 [dependencies]
-ordered-float = "1.0"
 byteorder = "1.3"
 integer-encoding = ">=1.1.4" # https://issues.apache.org/jira/browse/THRIFT-5131
 log = "0.4"
+ordered-float = "1.0"
 threadpool = "1.7"
diff --git a/lib/rs/README.md b/lib/rs/README.md
index 1b608b2..555d219 100644
--- a/lib/rs/README.md
+++ b/lib/rs/README.md
@@ -48,7 +48,7 @@
 
 ##### Thrift 0.14.0
 
-* **[THRIFT-5158]** - Rust library and generator now support Rust 2018 only
+* **[THRIFT-5158]** - Rust library and generator now support Rust 2018 only. Required rust 1.40.0 or higher
 
     The Rust `thrift` library was updated to Rust 2018 via `cargo fix --edition`.
     All test code in the repo was updated as well. The code generator was also updated
diff --git a/lib/rs/src/errors.rs b/lib/rs/src/errors.rs
index 2167875..41a055e 100644
--- a/lib/rs/src/errors.rs
+++ b/lib/rs/src/errors.rs
@@ -236,8 +236,8 @@
         i.read_struct_end()?;
 
         Ok(ApplicationError {
-            kind: kind,
-            message: message,
+            kind,
+            message,
         })
     }
 
@@ -283,7 +283,7 @@
 }
 
 impl Debug for Error {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         match *self {
             Error::Transport(ref e) => Debug::fmt(e, f),
             Error::Protocol(ref e) => Debug::fmt(e, f),
@@ -294,7 +294,7 @@
 }
 
 impl Display for Error {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         match *self {
             Error::Transport(ref e) => Display::fmt(e, f),
             Error::Protocol(ref e) => Display::fmt(e, f),
@@ -362,7 +362,7 @@
     /// Create a new `TransportError`.
     pub fn new<S: Into<String>>(kind: TransportErrorKind, message: S) -> TransportError {
         TransportError {
-            kind: kind,
+            kind,
             message: message.into(),
         }
     }
@@ -404,7 +404,7 @@
 }
 
 impl Display for TransportError {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.description())
     }
 }
@@ -490,7 +490,7 @@
     /// Create a new `ProtocolError`.
     pub fn new<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> ProtocolError {
         ProtocolError {
-            kind: kind,
+            kind,
             message: message.into(),
         }
     }
@@ -534,7 +534,7 @@
 }
 
 impl Display for ProtocolError {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.description())
     }
 }
@@ -581,7 +581,7 @@
     /// Create a new `ApplicationError`.
     pub fn new<S: Into<String>>(kind: ApplicationErrorKind, message: S) -> ApplicationError {
         ApplicationError {
-            kind: kind,
+            kind,
             message: message.into(),
         }
     }
@@ -638,7 +638,7 @@
 }
 
 impl Display for ApplicationError {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.description())
     }
 }
diff --git a/lib/rs/src/lib.rs b/lib/rs/src/lib.rs
index b762e05..f71c3e8 100644
--- a/lib/rs/src/lib.rs
+++ b/lib/rs/src/lib.rs
@@ -49,14 +49,6 @@
 #![doc(test(attr(allow(unused_variables), deny(warnings))))]
 #![deny(bare_trait_objects)]
 
-extern crate byteorder;
-extern crate ordered_float;
-extern crate integer_encoding;
-extern crate threadpool;
-
-#[macro_use]
-extern crate log;
-
 // NOTE: this macro has to be defined before any modules. See:
 // https://danielkeep.github.io/quick-intro-to-macros.html#some-more-gotchas
 
diff --git a/lib/rs/src/protocol/binary.rs b/lib/rs/src/protocol/binary.rs
index 0ef65e5..22b496c 100644
--- a/lib/rs/src/protocol/binary.rs
+++ b/lib/rs/src/protocol/binary.rs
@@ -26,7 +26,7 @@
 use crate::transport::{TReadTransport, TWriteTransport};
 use crate::{ProtocolError, ProtocolErrorKind};
 
-const BINARY_PROTOCOL_VERSION_1: u32 = 0x80010000;
+const BINARY_PROTOCOL_VERSION_1: u32 = 0x8001_0000;
 
 /// Read messages encoded in the Thrift simple binary encoding.
 ///
@@ -69,8 +69,8 @@
     /// version number in the protocol header.
     pub fn new(transport: T, strict: bool) -> TBinaryInputProtocol<T> {
         TBinaryInputProtocol {
-            strict: strict,
-            transport: transport,
+            strict,
+            transport,
         }
     }
 }
@@ -79,7 +79,7 @@
 where
     T: TReadTransport,
 {
-    #[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))]
+    #[allow(clippy::collapsible_if)]
     fn read_message_begin(&mut self) -> crate::Result<TMessageIdentifier> {
         let mut first_bytes = vec![0; 4];
         self.transport.read_exact(&mut first_bytes[..])?;
@@ -295,8 +295,8 @@
     /// protocol version number in the protocol header.
     pub fn new(transport: T, strict: bool) -> TBinaryOutputProtocol<T> {
         TBinaryOutputProtocol {
-            strict: strict,
-            transport: transport,
+            strict,
+            transport,
         }
     }
 }
@@ -520,7 +520,7 @@
         let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
         assert!(o_prot.write_message_begin(&ident).is_ok());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 16] = [
             0x80,
             0x01,
@@ -550,7 +550,7 @@
         let ident = TMessageIdentifier::new("test", TMessageType::Call, 1);
         assert!(o_prot.write_message_begin(&ident).is_ok());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 13] = [
             0x00,
             0x00,
@@ -577,7 +577,7 @@
         let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
         assert!(o_prot.write_message_begin(&ident).is_ok());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 16] = [
             0x80,
             0x01,
@@ -607,7 +607,7 @@
         let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10);
         assert!(o_prot.write_message_begin(&ident).is_ok());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 13] = [
             0x00,
             0x00,
@@ -892,7 +892,7 @@
     fn must_round_trip_bytes() {
         let (mut i_prot, mut o_prot) = test_objects(true);
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let bytes: [u8; 25] = [
             0x20,
             0xFD,
diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs
index f33c020..6fa364f 100644
--- a/lib/rs/src/protocol/compact.rs
+++ b/lib/rs/src/protocol/compact.rs
@@ -76,7 +76,7 @@
             last_read_field_id: 0,
             read_field_id_stack: Vec::new(),
             pending_read_bool_value: None,
-            transport: transport,
+            transport,
         }
     }
 
@@ -193,7 +193,7 @@
 
                 Ok(TFieldIdentifier {
                     name: None,
-                    field_type: field_type,
+                    field_type,
                     id: Some(self.last_read_field_id),
                 })
             }
@@ -371,7 +371,7 @@
             last_write_field_id: 0,
             write_field_id_stack: Vec::new(),
             pending_write_bool_field_identifier: None,
-            transport: transport,
+            transport,
         }
     }
 
@@ -673,7 +673,7 @@
             431
         )));
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 8] = [
             0x82, /* protocol ID */
             0x21, /* message type | protocol version */
@@ -695,10 +695,10 @@
         assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new(
             "bar",
             TMessageType::Reply,
-            991828
+            991_828
         )));
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 9] = [
             0x82, /* protocol ID */
             0x41, /* message type | protocol version */
@@ -743,7 +743,7 @@
     fn must_round_trip_message_begin() {
         let (mut i_prot, mut o_prot) = test_objects();
 
-        let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1283948);
+        let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948);
 
         assert_success!(o_prot.write_message_begin(&ident));
 
@@ -787,7 +787,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 5] = [
             0x03, /* field type */
             0x00, /* first field id */
@@ -902,7 +902,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 4] = [
             0x15, /* field delta (1) | field type */
             0x1A, /* field delta (1) | field type */
@@ -1015,7 +1015,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 8] = [
             0x05, /* field type */
             0x00, /* first field id */
@@ -1139,7 +1139,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 10] = [
             0x16, /* field delta (1) | field type */
             0x85, /* field delta (8) | field type */
@@ -1156,6 +1156,7 @@
         assert_eq_written_bytes!(o_prot, expected);
     }
 
+    #[allow(clippy::cognitive_complexity)]
     #[test]
     fn must_round_trip_struct_with_mix_of_long_and_delta_fields() {
         let (mut i_prot, mut o_prot) = test_objects();
@@ -1304,7 +1305,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 7] = [
             0x16, /* field delta (1) | field type */
             0x85, /* field delta (8) | field type */
@@ -1318,6 +1319,7 @@
         assert_eq_written_bytes!(o_prot, expected);
     }
 
+    #[allow(clippy::cognitive_complexity)]
     #[test]
     fn must_round_trip_nested_structs_0() {
         // last field of the containing struct is a delta
@@ -1477,7 +1479,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 7] = [
             0x16, /* field delta (1) | field type */
             0x85, /* field delta (8) | field type */
@@ -1491,6 +1493,7 @@
         assert_eq_written_bytes!(o_prot, expected);
     }
 
+    #[allow(clippy::cognitive_complexity)]
     #[test]
     fn must_round_trip_nested_structs_1() {
         // last field of the containing struct is a delta
@@ -1650,7 +1653,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 7] = [
             0x16, /* field delta (1) | field type */
             0x08, /* field type */
@@ -1664,6 +1667,7 @@
         assert_eq_written_bytes!(o_prot, expected);
     }
 
+    #[allow(clippy::cognitive_complexity)]
     #[test]
     fn must_round_trip_nested_structs_2() {
         let (mut i_prot, mut o_prot) = test_objects();
@@ -1820,7 +1824,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 8] = [
             0x16, /* field delta (1) | field type */
             0x08, /* field type */
@@ -1835,6 +1839,7 @@
         assert_eq_written_bytes!(o_prot, expected);
     }
 
+    #[allow(clippy::cognitive_complexity)]
     #[test]
     fn must_round_trip_nested_structs_3() {
         // last field of the containing struct is a full write
@@ -1986,7 +1991,7 @@
         assert_success!(o_prot.write_field_stop());
         assert_success!(o_prot.write_struct_end());
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 7] = [
             0x11, /* field delta (1) | true */
             0x82, /* field delta (8) | false */
@@ -2000,6 +2005,7 @@
         assert_eq_written_bytes!(o_prot, expected);
     }
 
+    #[allow(clippy::cognitive_complexity)]
     #[test]
     fn must_round_trip_bool_field() {
         let (mut i_prot, mut o_prot) = test_objects();
@@ -2245,7 +2251,7 @@
     fn must_round_trip_large_sized_set_begin() {
         let (mut i_prot, mut o_prot) = test_objects();
 
-        let ident = TSetIdentifier::new(TType::Map, 3928429);
+        let ident = TSetIdentifier::new(TType::Map, 3_928_429);
 
         assert_success!(o_prot.write_set_begin(&ident));
 
@@ -2312,7 +2318,7 @@
     fn must_round_trip_map_begin() {
         let (mut i_prot, mut o_prot) = test_objects();
 
-        let ident = TMapIdentifier::new(TType::Map, TType::List, 1928349);
+        let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349);
 
         assert_success!(o_prot.write_map_begin(&ident));
 
@@ -2403,11 +2409,13 @@
     fn must_read_write_double() {
         let (mut i_prot, mut o_prot) = test_objects();
 
-        let double = 3.141592653589793238462643;
+        #[allow(clippy::approx_constant)]
+        let double = 3.141_592_653_589_793;
         o_prot.write_double(double).unwrap();
         copy_write_buffer_to_read_buffer!(o_prot);
 
-        assert_eq!(i_prot.read_double().unwrap(), double);
+        let read_double = i_prot.read_double().unwrap();
+        assert!(read_double - double < std::f64::EPSILON);
     }
 
     #[test]
@@ -2415,11 +2423,11 @@
         let (_, mut o_prot) = test_objects();
         let expected = [24, 45, 68, 84, 251, 33, 9, 64];
 
-        let double = 3.141592653589793238462643;
+        #[allow(clippy::approx_constant)]
+        let double = 3.141_592_653_589_793;
         o_prot.write_double(double).unwrap();
 
         assert_eq_written_bytes!(o_prot, expected);
-
     }
 
     fn assert_no_write<F>(mut write_fn: F)
diff --git a/lib/rs/src/protocol/mod.rs b/lib/rs/src/protocol/mod.rs
index b0e9118..f9c1f72 100644
--- a/lib/rs/src/protocol/mod.rs
+++ b/lib/rs/src/protocol/mod.rs
@@ -610,8 +610,8 @@
     ) -> TMessageIdentifier {
         TMessageIdentifier {
             name: name.into(),
-            message_type: message_type,
-            sequence_number: sequence_number,
+            message_type,
+            sequence_number,
         }
     }
 }
@@ -660,7 +660,7 @@
     {
         TFieldIdentifier {
             name: name.into().map(|n| n.into()),
-            field_type: field_type,
+            field_type,
             id: id.into(),
         }
     }
@@ -680,8 +680,8 @@
     /// `element_type`.
     pub fn new(element_type: TType, size: i32) -> TListIdentifier {
         TListIdentifier {
-            element_type: element_type,
-            size: size,
+            element_type,
+            size,
         }
     }
 }
@@ -700,8 +700,8 @@
     /// `element_type`.
     pub fn new(element_type: TType, size: i32) -> TSetIdentifier {
         TSetIdentifier {
-            element_type: element_type,
-            size: size,
+            element_type,
+            size,
         }
     }
 }
@@ -728,7 +728,7 @@
         TMapIdentifier {
             key_type: key_type.into(),
             value_type: value_type.into(),
-            size: size,
+            size,
         }
     }
 }
@@ -747,7 +747,7 @@
 }
 
 impl Display for TMessageType {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         match *self {
             TMessageType::Call => write!(f, "Call"),
             TMessageType::Reply => write!(f, "Reply"),
@@ -822,7 +822,7 @@
 }
 
 impl Display for TType {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         match *self {
             TType::Stop => write!(f, "STOP"),
             TType::Void => write!(f, "void"),
diff --git a/lib/rs/src/protocol/multiplexed.rs b/lib/rs/src/protocol/multiplexed.rs
index 9c3ba7c..83498fb 100644
--- a/lib/rs/src/protocol/multiplexed.rs
+++ b/lib/rs/src/protocol/multiplexed.rs
@@ -203,7 +203,7 @@
         let ident = TMessageIdentifier::new("bar", TMessageType::Call, 2);
         assert_success!(o_prot.write_message_begin(&ident));
 
-        #[cfg_attr(rustfmt, rustfmt::skip)]
+        #[rustfmt::skip]
         let expected: [u8; 19] = [
             0x80,
             0x01, /* protocol identifier */
diff --git a/lib/rs/src/protocol/stored.rs b/lib/rs/src/protocol/stored.rs
index c5e02fe..179ae07 100644
--- a/lib/rs/src/protocol/stored.rs
+++ b/lib/rs/src/protocol/stored.rs
@@ -92,7 +92,7 @@
     pub fn new(
         wrapped: &mut dyn TInputProtocol,
         message_ident: TMessageIdentifier,
-    ) -> TStoredInputProtocol {
+    ) -> TStoredInputProtocol<'_> {
         TStoredInputProtocol {
             inner: wrapped,
             message_ident: message_ident.into(),
diff --git a/lib/rs/src/server/multiplexed.rs b/lib/rs/src/server/multiplexed.rs
index 3d688fa..4f41f24 100644
--- a/lib/rs/src/server/multiplexed.rs
+++ b/lib/rs/src/server/multiplexed.rs
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use log::debug;
+
 use std::collections::HashMap;
 use std::convert::Into;
 use std::fmt;
@@ -25,7 +27,7 @@
 
 use super::{handle_process_result, TProcessor};
 
-const MISSING_SEPARATOR_AND_NO_DEFAULT: &'static str =
+const MISSING_SEPARATOR_AND_NO_DEFAULT: &str =
     "missing service separator and no default processor set";
 type ThreadSafeProcessor = Box<dyn TProcessor + Send + Sync>;
 
@@ -70,7 +72,7 @@
     /// Returns success if a new entry was inserted. Returns an error if:
     /// * A processor exists for `service_name`
     /// * You attempt to register a processor as default, and an existing default exists
-    #[cfg_attr(feature = "cargo-clippy", allow(map_entry))]
+    #[allow(clippy::map_entry)]
     pub fn register<S: Into<String>>(
         &mut self,
         service_name: S,
@@ -145,7 +147,7 @@
 }
 
 impl Debug for TMultiplexedProcessor {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         let stored = self.stored.lock().unwrap();
         write!(
             f,
diff --git a/lib/rs/src/server/threaded.rs b/lib/rs/src/server/threaded.rs
index 8373c46..64bf8bb 100644
--- a/lib/rs/src/server/threaded.rs
+++ b/lib/rs/src/server/threaded.rs
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use log::warn;
+
 use std::net::{TcpListener, TcpStream, ToSocketAddrs};
 use std::sync::Arc;
 use threadpool::ThreadPool;
diff --git a/lib/rs/src/transport/buffered.rs b/lib/rs/src/transport/buffered.rs
index 914a19b..ebdcdc2 100644
--- a/lib/rs/src/transport/buffered.rs
+++ b/lib/rs/src/transport/buffered.rs
@@ -200,7 +200,7 @@
         TBufferedWriteTransport {
             buf: Vec::with_capacity(write_capacity),
             cap: write_capacity,
-            channel: channel,
+            channel,
         }
     }
 }
@@ -347,8 +347,8 @@
 
         // fill the underlying transport's byte buffer
         let mut readable_bytes = [0u8; 10];
-        for i in 0..10 {
-            readable_bytes[i] = i as u8;
+        for (i, b) in readable_bytes.iter_mut().enumerate() {
+            *b = i as u8;
         }
 
         t.chan.set_readable_bytes(&readable_bytes);
@@ -365,8 +365,8 @@
         assert_eq!(&buf, &[0, 1, 2, 3, 4, 5, 6, 7]);
 
         // let's clear out the buffer and try read again
-        for i in 0..8 {
-            buf[i] = 0;
+        for b in &mut buf{
+            *b = 0;
         }
         let read_result = t.read(&mut buf);
 
diff --git a/lib/rs/src/transport/mem.rs b/lib/rs/src/transport/mem.rs
index 68fb265..fe1c543 100644
--- a/lib/rs/src/transport/mem.rs
+++ b/lib/rs/src/transport/mem.rs
@@ -153,7 +153,9 @@
             WriteHalf {
                 handle: TBufferChannel {
                     read: self.read.clone(),
-                    write: self.write.clone(),
+                    // NOTE: not cloning here, since this is the last statement
+                    // in this method and `write` can take ownership of `self.write`
+                    write: self.write,
                 },
             },
         ))
diff --git a/lib/rs/test/Cargo.toml b/lib/rs/test/Cargo.toml
index decc985..9341bd5 100644
--- a/lib/rs/test/Cargo.toml
+++ b/lib/rs/test/Cargo.toml
@@ -7,9 +7,7 @@
 publish = false
 
 [dependencies]
-clap = "<2.28.0"
-ordered-float = "1.0"
-try_from = "0.3"
+clap = "2.33"
 
 [dependencies.thrift]
 path = "../"
diff --git a/lib/rs/test/src/bin/kitchen_sink_client.rs b/lib/rs/test/src/bin/kitchen_sink_client.rs
index a777920..74197de 100644
--- a/lib/rs/test/src/bin/kitchen_sink_client.rs
+++ b/lib/rs/test/src/bin/kitchen_sink_client.rs
@@ -15,11 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[macro_use]
-extern crate clap;
-
-extern crate kitchen_sink;
-extern crate thrift;
+use clap::{clap_app, value_t};
 
 use std::convert::Into;
 
@@ -28,6 +24,8 @@
 use kitchen_sink::recursive;
 use kitchen_sink::recursive::{CoRec, CoRec2, RecList, RecTree, TTestServiceSyncClient};
 use kitchen_sink::ultimate::{FullMealServiceSyncClient, TFullMealServiceSyncClient};
+
+use thrift;
 use thrift::protocol::{
     TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, TCompactOutputProtocol,
     TInputProtocol, TOutputProtocol,
diff --git a/lib/rs/test/src/bin/kitchen_sink_server.rs b/lib/rs/test/src/bin/kitchen_sink_server.rs
index c53e887..6df39e4 100644
--- a/lib/rs/test/src/bin/kitchen_sink_server.rs
+++ b/lib/rs/test/src/bin/kitchen_sink_server.rs
@@ -15,11 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[macro_use]
-extern crate clap;
-extern crate kitchen_sink;
-extern crate thrift;
+use clap::{clap_app, value_t};
 
+use thrift;
 use thrift::protocol::{
     TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, TCompactInputProtocolFactory,
     TCompactOutputProtocolFactory, TInputProtocolFactory, TOutputProtocolFactory,
diff --git a/lib/rs/test/src/lib.rs b/lib/rs/test/src/lib.rs
index 9debdca..91fd027 100644
--- a/lib/rs/test/src/lib.rs
+++ b/lib/rs/test/src/lib.rs
@@ -15,8 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-extern crate thrift;
-
 pub mod base_one;
 pub mod base_two;
 pub mod midlayer;
diff --git a/test/rs/Cargo.toml b/test/rs/Cargo.toml
index deffd21..8a85d7c 100644
--- a/test/rs/Cargo.toml
+++ b/test/rs/Cargo.toml
@@ -8,10 +8,8 @@
 
 [dependencies]
 clap = "2.33"
-env_logger = "0.4.0"
+env_logger = "0.8"
 log = "0.4"
-ordered-float = "1.0"
-try_from = "0.3"
 
 [dependencies.thrift]
 path = "../../lib/rs"
diff --git a/test/rs/src/bin/test_client.rs b/test/rs/src/bin/test_client.rs
index 3206deb..6cbc238 100644
--- a/test/rs/src/bin/test_client.rs
+++ b/test/rs/src/bin/test_client.rs
@@ -15,20 +15,15 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[macro_use]
-extern crate log;
-extern crate env_logger;
+use env_logger;
+use log::*;
+use clap::{clap_app, value_t};
 
-#[macro_use]
-extern crate clap;
-extern crate ordered_float;
-extern crate thrift;
-extern crate thrift_test; // huh. I have to do this to use my lib
-
-use ordered_float::OrderedFloat;
 use std::collections::{BTreeMap, BTreeSet};
 use std::fmt::Debug;
 
+use thrift;
+use thrift::OrderedFloat;
 use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol,
                        TCompactOutputProtocol, TInputProtocol, TMultiplexedOutputProtocol,
                        TOutputProtocol};
@@ -38,7 +33,7 @@
 use thrift_test::*;
 
 fn main() {
-    env_logger::init().expect("logger setup failed");
+    env_logger::init();
 
     debug!("initialized logger - running cross-test client");
 
@@ -167,7 +162,7 @@
 type BuildThriftTestClient = ThriftTestSyncClient<Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>>;
 type BuiltSecondServiceClient = SecondServiceSyncClient<Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>>;
 
-#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
+#[allow(clippy::cognitive_complexity)]
 fn make_thrift_calls(
     thrift_test_client: &mut BuildThriftTestClient,
     second_service_client: &mut Option<BuiltSecondServiceClient>,
@@ -191,7 +186,7 @@
     verify_expected_result(thrift_test_client.test_byte(42), 42)?;
 
     info!("testi32");
-    verify_expected_result(thrift_test_client.test_i32(1159348374), 1159348374)?;
+    verify_expected_result(thrift_test_client.test_i32(1_159_348_374), 1_159_348_374)?;
 
     info!("testi64");
     // try!(verify_expected_result(thrift_test_client.test_i64(-8651829879438294565),
@@ -231,14 +226,14 @@
         let x_snd = Xtruct {
             string_thing: Some("foo".to_owned()),
             byte_thing: Some(12),
-            i32_thing: Some(219129),
-            i64_thing: Some(12938492818),
+            i32_thing: Some(219_129),
+            i64_thing: Some(12_938_492_818),
         };
         let x_cmp = Xtruct {
             string_thing: Some("foo".to_owned()),
             byte_thing: Some(12),
-            i32_thing: Some(219129),
-            i64_thing: Some(12938492818),
+            i32_thing: Some(219_129),
+            i64_thing: Some(12_938_492_818),
         };
         verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp)?;
     }
@@ -264,11 +259,11 @@
                 Xtruct {
                     string_thing: Some("foo".to_owned()),
                     byte_thing: Some(1),
-                    i32_thing: Some(324382098),
-                    i64_thing: Some(12938492818),
+                    i32_thing: Some(324_382_098),
+                    i64_thing: Some(12_938_492_818),
                 },
             ),
-            i32_thing: Some(293481098),
+            i32_thing: Some(293_481_098),
         };
         let x_cmp = Xtruct2 {
             byte_thing: Some(32),
@@ -276,11 +271,11 @@
                 Xtruct {
                     string_thing: Some("foo".to_owned()),
                     byte_thing: Some(1),
-                    i32_thing: Some(324382098),
-                    i64_thing: Some(12938492818),
+                    i32_thing: Some(324_382_098),
+                    i64_thing: Some(12_938_492_818),
                 },
             ),
-            i32_thing: Some(293481098),
+            i32_thing: Some(293_481_098),
         };
         verify_expected_result(thrift_test_client.test_nest(x_snd), x_cmp)?;
     }
@@ -314,12 +309,12 @@
     info!("testSet");
     {
         let mut s_snd: BTreeSet<i32> = BTreeSet::new();
-        s_snd.insert(293481);
+        s_snd.insert(293_481);
         s_snd.insert(23);
         s_snd.insert(3234);
 
         let mut s_cmp: BTreeSet<i32> = BTreeSet::new();
-        s_cmp.insert(293481);
+        s_cmp.insert(293_481);
         s_cmp.insert(23);
         s_cmp.insert(3234);
 
@@ -386,12 +381,12 @@
         let s_cmp = Xtruct {
             string_thing: Some("Hello2".to_owned()),
             byte_thing: Some(1),
-            i32_thing: Some(-123948),
-            i64_thing: Some(-19234123981),
+            i32_thing: Some(-123_948),
+            i64_thing: Some(-19_234_123_981),
         };
 
         verify_expected_result(
-            thrift_test_client.test_multi(1, -123948, -19234123981, m_snd, Numberz::Eight, 81),
+            thrift_test_client.test_multi(1, -123_948, -19_234_123_981, m_snd, Numberz::Eight, 81),
             s_cmp,
         )?;
     }
@@ -429,8 +424,8 @@
             Xtruct {
                 string_thing: Some("baz".to_owned()),
                 byte_thing: Some(0),
-                i32_thing: Some(3948539),
-                i64_thing: Some(-12938492),
+                i32_thing: Some(3_948_539),
+                i64_thing: Some(-12_938_492),
             },
         );
 
@@ -453,7 +448,7 @@
         s_cmp.insert(1 as UserId, s_cmp_nested_1);
         s_cmp.insert(2 as UserId, s_cmp_nested_2);
 
-        verify_expected_result(thrift_test_client.test_insanity(insanity.clone()), s_cmp)?;
+        verify_expected_result(thrift_test_client.test_insanity(insanity), s_cmp)?;
     }
 
     info!("testException - remote throws Xception");
@@ -583,7 +578,6 @@
     thrift_test_client.test_void()
 }
 
-#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
 fn verify_expected_result<T: Debug + PartialEq + Sized>(
     actual: Result<T, thrift::Error>,
     expected: T,
diff --git a/test/rs/src/bin/test_server.rs b/test/rs/src/bin/test_server.rs
index e57cc14..74be12d 100644
--- a/test/rs/src/bin/test_server.rs
+++ b/test/rs/src/bin/test_server.rs
@@ -15,21 +15,16 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[macro_use]
-extern crate log;
-extern crate env_logger;
+use env_logger;
+use log::*;
+use clap::{clap_app, value_t};
 
-#[macro_use]
-extern crate clap;
-extern crate ordered_float;
-extern crate thrift;
-extern crate thrift_test;
-
-use ordered_float::OrderedFloat;
 use std::collections::{BTreeMap, BTreeSet};
 use std::thread;
 use std::time::Duration;
 
+use thrift;
+use thrift::OrderedFloat;
 use thrift::protocol::{TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory,
                        TCompactInputProtocolFactory, TCompactOutputProtocolFactory,
                        TInputProtocolFactory, TOutputProtocolFactory};
@@ -40,7 +35,7 @@
 use thrift_test::*;
 
 fn main() {
-    env_logger::init().expect("logger setup failed");
+    env_logger::init();
 
     debug!("initialized logger - running cross-test server");
 
@@ -274,7 +269,7 @@
         info!("testInsanity({:?})", argument);
         let mut map_0: BTreeMap<Numberz, Insanity> = BTreeMap::new();
         map_0.insert(Numberz::Two, argument.clone());
-        map_0.insert(Numberz::Three, argument.clone());
+        map_0.insert(Numberz::Three, argument);
 
         let mut map_1: BTreeMap<Numberz, Insanity> = BTreeMap::new();
         let insanity = Insanity {
diff --git a/test/rs/src/lib.rs b/test/rs/src/lib.rs
index 10523f0..3c7cfc0 100644
--- a/test/rs/src/lib.rs
+++ b/test/rs/src/lib.rs
@@ -15,9 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-extern crate ordered_float;
-extern crate thrift;
-extern crate try_from;
+
+
+
 
 mod thrift_test;
 pub use crate::thrift_test::*;
diff --git a/tutorial/rs/Cargo.toml b/tutorial/rs/Cargo.toml
index d8e2a9a..5e21d51 100644
--- a/tutorial/rs/Cargo.toml
+++ b/tutorial/rs/Cargo.toml
@@ -9,8 +9,6 @@
 
 [dependencies]
 clap = "2.33"
-ordered-float = "1.0"
-try_from = "0.3"
 
 [dependencies.thrift]
 path = "../../lib/rs"
diff --git a/tutorial/rs/README.md b/tutorial/rs/README.md
index 166854b..97b1490 100644
--- a/tutorial/rs/README.md
+++ b/tutorial/rs/README.md
@@ -4,37 +4,22 @@
 
 1. Get the [Thrift compiler](https://thrift.apache.org).
 
-2. Add the following crates to your `Cargo.toml`.
+2. Add the thrift crate to your `Cargo.toml`.
 
 ```toml
 thrift = "x.y.z" # x.y.z is the version of the thrift compiler
-ordered-float = "0.3.0"
-try_from = "0.2.0"
 ```
 
-3. Add the same crates to your `lib.rs` or `main.rs`.
-
-```rust
-extern crate ordered_float;
-extern crate thrift;
-extern crate try_from;
-```
-
-4. Generate Rust sources for your IDL (for example, `Tutorial.thrift`).
+3. Generate Rust sources for your IDL (for example, `Tutorial.thrift`).
 
 ```shell
 thrift -out my_rust_program/src --gen rs -r Tutorial.thrift
 ```
 
-5. Use the generated source in your code.
+4. Use the generated source in your code.
 
 ```rust
-// add extern crates here, or in your lib.rs
-extern crate ordered_float;
-extern crate thrift;
-extern crate try_from;
-
-// generated Rust module
+// generated Rust module from Thrift IDL
 mod tutorial;
 
 use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol};
@@ -120,7 +105,7 @@
 ### Results and Errors
 
 The Thrift runtime library defines a `thrift::Result` and a `thrift::Error` type,
-both of which are used throught the runtime library and in all generated code.
+both of which are used throughout the runtime library and in all generated code.
 Conversions are defined from `std::io::Error`, `str` and `String` into
 `thrift::Error`.
 
diff --git a/tutorial/rs/src/bin/tutorial_client.rs b/tutorial/rs/src/bin/tutorial_client.rs
index 90a26d8..f7de23f 100644
--- a/tutorial/rs/src/bin/tutorial_client.rs
+++ b/tutorial/rs/src/bin/tutorial_client.rs
@@ -15,8 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[macro_use]
-extern crate clap;
+use clap::{clap_app, value_t};
 
 use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol};
 use thrift::transport::{
diff --git a/tutorial/rs/src/bin/tutorial_server.rs b/tutorial/rs/src/bin/tutorial_server.rs
index e4d1d2e..fbccb69 100644
--- a/tutorial/rs/src/bin/tutorial_server.rs
+++ b/tutorial/rs/src/bin/tutorial_server.rs
@@ -15,18 +15,17 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[macro_use]
-extern crate clap;
-
 use std::collections::HashMap;
 use std::convert::{From, Into};
 use std::default::Default;
 use std::sync::Mutex;
 
+use clap::{clap_app, value_t};
+
 use thrift::protocol::{TCompactInputProtocolFactory, TCompactOutputProtocolFactory};
 use thrift::server::TServer;
-
 use thrift::transport::{TFramedReadTransportFactory, TFramedWriteTransportFactory};
+
 use thrift_tutorial::shared::{SharedServiceSyncHandler, SharedStruct};
 use thrift_tutorial::tutorial::{CalculatorSyncHandler, CalculatorSyncProcessor};
 use thrift_tutorial::tutorial::{InvalidOperation, Operation, Work};