diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9448a57f7f..962f9067a4e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1214,6 +1214,7 @@ Released 2018-09-13
 [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines
 [`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg
 [`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str
+[`transmute_float_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_float_to_int
 [`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool
 [`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char
 [`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float
diff --git a/README.md b/README.md
index 97a7c97b49a..6133fa4c3a5 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
 
-[There are 339 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are 340 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
 We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
 
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index d14f946c8eb..736ff30c81a 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -735,6 +735,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
         &trait_bounds::TYPE_REPETITION_IN_BOUNDS,
         &transmute::CROSSPOINTER_TRANSMUTE,
         &transmute::TRANSMUTE_BYTES_TO_STR,
+        &transmute::TRANSMUTE_FLOAT_TO_INT,
         &transmute::TRANSMUTE_INT_TO_BOOL,
         &transmute::TRANSMUTE_INT_TO_CHAR,
         &transmute::TRANSMUTE_INT_TO_FLOAT,
@@ -1586,6 +1587,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
         LintId::of(&mutex_atomic::MUTEX_INTEGER),
         LintId::of(&needless_borrow::NEEDLESS_BORROW),
         LintId::of(&path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
+        LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT),
         LintId::of(&use_self::USE_SELF),
     ]);
 }
diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs
index 12de3023dad..3c63ef765fe 100644
--- a/clippy_lints/src/transmute.rs
+++ b/clippy_lints/src/transmute.rs
@@ -190,6 +190,28 @@ declare_clippy_lint! {
     "transmutes from an integer to a float"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for transmutes from a float to an integer.
+    ///
+    /// **Why is this bad?** Transmutes are dangerous and error-prone, whereas `to_bits` is intuitive
+    /// and safe.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// unsafe {
+    ///     let _: u32 = std::mem::transmute(1f32);
+    /// }
+    ///
+    /// // should be:
+    /// let _: u32 = 1f32.to_bits();
+    /// ```
+    pub TRANSMUTE_FLOAT_TO_INT,
+    nursery,
+    "transmutes from a float to an integer"
+}
+
 declare_clippy_lint! {
     /// **What it does:** Checks for transmutes from a pointer to a pointer, or
     /// from a reference to a reference.
@@ -254,6 +276,7 @@ declare_lint_pass!(Transmute => [
     TRANSMUTE_BYTES_TO_STR,
     TRANSMUTE_INT_TO_BOOL,
     TRANSMUTE_INT_TO_FLOAT,
+    TRANSMUTE_FLOAT_TO_INT,
     UNSOUND_COLLECTION_TRANSMUTE,
 ]);
 
@@ -520,6 +543,50 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
                             );
                         },
                     ),
+                    (&ty::Float(float_ty), &ty::Int(_)) | (&ty::Float(float_ty), &ty::Uint(_)) => span_lint_and_then(
+                        cx,
+                        TRANSMUTE_FLOAT_TO_INT,
+                        e.span,
+                        &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+                        |db| {
+                            let mut expr = &args[0];
+                            let mut arg = sugg::Sugg::hir(cx, expr, "..");
+
+                            if let ExprKind::Unary(UnOp::UnNeg, inner_expr) = &expr.kind {
+                                expr = &inner_expr;
+                            }
+
+                            if_chain! {
+                                // if the expression is a float literal and it is unsuffixed then
+                                // add a suffix so the suggestion is valid and unambiguous
+                                let op = format!("{}{}", arg, float_ty.name_str()).into();
+                                if let ExprKind::Lit(lit) = &expr.kind;
+                                if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node;
+                                then {
+                                    match arg {
+                                        sugg::Sugg::MaybeParen(_) => arg = sugg::Sugg::MaybeParen(op),
+                                        _ => arg = sugg::Sugg::NonParen(op)
+                                    }
+                                }
+                            }
+
+                            arg = sugg::Sugg::NonParen(format!("{}.to_bits()", arg.maybe_par()).into());
+
+                            // cast the result of `to_bits` if `to_ty` is signed
+                            arg = if let ty::Int(int_ty) = to_ty.kind {
+                                arg.as_ty(int_ty.name_str().to_string())
+                            } else {
+                                arg
+                            };
+
+                            db.span_suggestion(
+                                e.span,
+                                "consider using",
+                                arg.to_string(),
+                                Applicability::Unspecified,
+                            );
+                        },
+                    ),
                     (&ty::Adt(ref from_adt, ref from_substs), &ty::Adt(ref to_adt, ref to_substs)) => {
                         if from_adt.did != to_adt.did ||
                                 !COLLECTIONS.iter().any(|path| match_def_path(cx, to_adt.did, path)) {
diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs
index 1f1c24b2c30..f4ebf6cbd91 100644
--- a/src/lintlist/mod.rs
+++ b/src/lintlist/mod.rs
@@ -6,7 +6,7 @@ pub use lint::Lint;
 pub use lint::LINT_LEVELS;
 
 // begin lint list, do not remove this comment, it’s used in `update_lints`
-pub const ALL_LINTS: [Lint; 339] = [
+pub const ALL_LINTS: [Lint; 340] = [
     Lint {
         name: "absurd_extreme_comparisons",
         group: "correctness",
@@ -1953,6 +1953,13 @@ pub const ALL_LINTS: [Lint; 339] = [
         deprecation: None,
         module: "transmute",
     },
+    Lint {
+        name: "transmute_float_to_int",
+        group: "nursery",
+        desc: "transmutes from a float to an integer",
+        deprecation: None,
+        module: "transmute",
+    },
     Lint {
         name: "transmute_int_to_bool",
         group: "complexity",
diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs
new file mode 100644
index 00000000000..ce942751ada
--- /dev/null
+++ b/tests/ui/transmute_float_to_int.rs
@@ -0,0 +1,12 @@
+#[warn(clippy::transmute_float_to_int)]
+
+fn float_to_int() {
+    let _: u32 = unsafe { std::mem::transmute(1f32) };
+    let _: i32 = unsafe { std::mem::transmute(1f32) };
+    let _: u64 = unsafe { std::mem::transmute(1f64) };
+    let _: i64 = unsafe { std::mem::transmute(1f64) };
+    let _: u64 = unsafe { std::mem::transmute(1.0) };
+    let _: u64 = unsafe { std::mem::transmute(-1.0) };
+}
+
+fn main() {}
diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr
new file mode 100644
index 00000000000..eb786bb39f9
--- /dev/null
+++ b/tests/ui/transmute_float_to_int.stderr
@@ -0,0 +1,40 @@
+error: transmute from a `f32` to a `u32`
+  --> $DIR/transmute_float_to_int.rs:4:27
+   |
+LL |     let _: u32 = unsafe { std::mem::transmute(1f32) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits()`
+   |
+   = note: `-D clippy::transmute-float-to-int` implied by `-D warnings`
+
+error: transmute from a `f32` to a `i32`
+  --> $DIR/transmute_float_to_int.rs:5:27
+   |
+LL |     let _: i32 = unsafe { std::mem::transmute(1f32) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32`
+
+error: transmute from a `f64` to a `u64`
+  --> $DIR/transmute_float_to_int.rs:6:27
+   |
+LL |     let _: u64 = unsafe { std::mem::transmute(1f64) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()`
+
+error: transmute from a `f64` to a `i64`
+  --> $DIR/transmute_float_to_int.rs:7:27
+   |
+LL |     let _: i64 = unsafe { std::mem::transmute(1f64) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits() as i64`
+
+error: transmute from a `f64` to a `u64`
+  --> $DIR/transmute_float_to_int.rs:8:27
+   |
+LL |     let _: u64 = unsafe { std::mem::transmute(1.0) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.0f64.to_bits()`
+
+error: transmute from a `f64` to a `u64`
+  --> $DIR/transmute_float_to_int.rs:9:27
+   |
+LL |     let _: u64 = unsafe { std::mem::transmute(-1.0) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()`
+
+error: aborting due to 6 previous errors
+