diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2373cb87eed..c9bea1e8ef5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -689,6 +689,7 @@ All notable changes to this project will be documented in this file.
 [`float_cmp`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp
 [`float_cmp_const`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#float_cmp_const
 [`fn_to_numeric_cast`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast
+[`fn_to_numeric_cast_with_truncation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation
 [`for_kv_map`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_kv_map
 [`for_loop_over_option`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_option
 [`for_loop_over_result`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#for_loop_over_result
diff --git a/README.md b/README.md
index f332a3f645d..40ece34c6fa 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ We are currently in the process of discussing Clippy 1.0 via the RFC process in
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
 
-[There are 278 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)
+[There are 279 lints included in this crate!](https://rust-lang-nursery.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 b181a4c17ca..3779b09ecf3 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -698,6 +698,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         types::CAST_PTR_ALIGNMENT,
         types::CHAR_LIT_AS_U8,
         types::FN_TO_NUMERIC_CAST,
+        types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
         types::IMPLICIT_HASHER,
         types::LET_UNIT_VALUE,
         types::OPTION_OPTION,
@@ -791,6 +792,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         returns::NEEDLESS_RETURN,
         strings::STRING_LIT_AS_BYTES,
         types::FN_TO_NUMERIC_CAST,
+        types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
         types::IMPLICIT_HASHER,
         types::LET_UNIT_VALUE,
         unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs
index f39a26db509..d3aa8de825b 100644
--- a/clippy_lints/src/types.rs
+++ b/clippy_lints/src/types.rs
@@ -746,6 +746,32 @@ declare_clippy_lint! {
     "casting a function pointer to a numeric type other than usize"
 }
 
+/// **What it does:** Checks for casts of a function pointer to a numeric type not wide enough to
+/// store address.
+///
+/// **Why is this bad?**
+/// Such a cast discards some bits of the function's address. If this is intended, it would be more
+/// clearly expressed by casting to usize first, then casting the usize to the intended type (with
+/// a comment) to perform the truncation.
+///
+/// **Example**
+///
+/// ```rust
+/// // Bad
+/// fn fn1() -> i16 { 1 };
+/// let _ = fn1 as i32;
+///
+/// // Better: Cast to usize first, then comment with the reason for the truncation
+/// fn fn2() -> i16 { 1 };
+/// let fn_ptr = fn2 as usize;
+/// let fn_ptr_truncated = fn_ptr as i32;
+/// ```
+declare_clippy_lint! {
+    pub FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
+    style,
+    "casting a function pointer to a numeric type not wide enough to store the address"
+}
+
 /// Returns the size in bits of an integral type.
 /// Will return 0 if the type is not an int or uint variant
 fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_, '_, '_>) -> u64 {
@@ -1054,7 +1080,19 @@ fn lint_fn_to_numeric_cast(cx: &LateContext<'_, '_>, expr: &Expr, cast_expr: &Ex
     match cast_from.sty {
         ty::FnDef(..) | ty::FnPtr(_) => {
             let from_snippet = snippet(cx, cast_expr.span, "x");
-            if cast_to.sty != ty::Uint(UintTy::Usize) {
+
+            let to_nbits = int_ty_to_nbits(cast_to, cx.tcx);
+            if to_nbits < cx.tcx.data_layout.pointer_size.bits() {
+                span_lint_and_sugg(
+                    cx,
+                    FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
+                    expr.span,
+                    &format!("casting function pointer `{}` to `{}`, which truncates the value", from_snippet, cast_to),
+                    "try",
+                    format!("{} as usize", from_snippet)
+                );
+
+            } else if cast_to.sty != ty::Uint(UintTy::Usize) {
                 span_lint_and_sugg(
                     cx,
                     FN_TO_NUMERIC_CAST,
diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs
index d250af61847..6d0fd3d8ab8 100644
--- a/tests/ui/fn_to_numeric_cast.rs
+++ b/tests/ui/fn_to_numeric_cast.rs
@@ -1,6 +1,6 @@
 #![feature(tool_lints)]
 
-#[warn(clippy::fn_to_numeric_cast)]
+#![warn(clippy::fn_to_numeric_cast)]
 
 fn foo() -> String { String::new() }
 
diff --git a/tests/ui/fn_to_numeric_cast.stderr b/tests/ui/fn_to_numeric_cast.stderr
new file mode 100644
index 00000000000..be8bc9058b4
--- /dev/null
+++ b/tests/ui/fn_to_numeric_cast.stderr
@@ -0,0 +1,142 @@
+error: casting function pointer `foo` to `i8`
+ --> $DIR/fn_to_numeric_cast.rs:8:13
+  |
+8 |     let _ = foo as i8;
+  |             ^^^^^^^^^ help: try: `foo as usize`
+  |
+  = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings`
+
+error: casting function pointer `foo` to `i16`
+ --> $DIR/fn_to_numeric_cast.rs:9:13
+  |
+9 |     let _ = foo as i16;
+  |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `i32`
+  --> $DIR/fn_to_numeric_cast.rs:10:13
+   |
+10 |     let _ = foo as i32;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `i64`
+  --> $DIR/fn_to_numeric_cast.rs:11:13
+   |
+11 |     let _ = foo as i64;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `i128`
+  --> $DIR/fn_to_numeric_cast.rs:12:13
+   |
+12 |     let _ = foo as i128;
+   |             ^^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `isize`
+  --> $DIR/fn_to_numeric_cast.rs:13:13
+   |
+13 |     let _ = foo as isize;
+   |             ^^^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u8`
+  --> $DIR/fn_to_numeric_cast.rs:15:13
+   |
+15 |     let _ = foo as u8;
+   |             ^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u16`
+  --> $DIR/fn_to_numeric_cast.rs:16:13
+   |
+16 |     let _ = foo as u16;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u32`
+  --> $DIR/fn_to_numeric_cast.rs:17:13
+   |
+17 |     let _ = foo as u32;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u64`
+  --> $DIR/fn_to_numeric_cast.rs:18:13
+   |
+18 |     let _ = foo as u64;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u128`
+  --> $DIR/fn_to_numeric_cast.rs:19:13
+   |
+19 |     let _ = foo as u128;
+   |             ^^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `abc` to `i8`
+  --> $DIR/fn_to_numeric_cast.rs:28:13
+   |
+28 |     let _ = abc as i8;
+   |             ^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `i16`
+  --> $DIR/fn_to_numeric_cast.rs:29:13
+   |
+29 |     let _ = abc as i16;
+   |             ^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `i32`
+  --> $DIR/fn_to_numeric_cast.rs:30:13
+   |
+30 |     let _ = abc as i32;
+   |             ^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `i64`
+  --> $DIR/fn_to_numeric_cast.rs:31:13
+   |
+31 |     let _ = abc as i64;
+   |             ^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `i128`
+  --> $DIR/fn_to_numeric_cast.rs:32:13
+   |
+32 |     let _ = abc as i128;
+   |             ^^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `isize`
+  --> $DIR/fn_to_numeric_cast.rs:33:13
+   |
+33 |     let _ = abc as isize;
+   |             ^^^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `u8`
+  --> $DIR/fn_to_numeric_cast.rs:35:13
+   |
+35 |     let _ = abc as u8;
+   |             ^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `u16`
+  --> $DIR/fn_to_numeric_cast.rs:36:13
+   |
+36 |     let _ = abc as u16;
+   |             ^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `u32`
+  --> $DIR/fn_to_numeric_cast.rs:37:13
+   |
+37 |     let _ = abc as u32;
+   |             ^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `u64`
+  --> $DIR/fn_to_numeric_cast.rs:38:13
+   |
+38 |     let _ = abc as u64;
+   |             ^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `abc` to `u128`
+  --> $DIR/fn_to_numeric_cast.rs:39:13
+   |
+39 |     let _ = abc as u128;
+   |             ^^^^^^^^^^^ help: try: `abc as usize`
+
+error: casting function pointer `f` to `i32`
+  --> $DIR/fn_to_numeric_cast.rs:46:5
+   |
+46 |     f as i32
+   |     ^^^^^^^^ help: try: `f as usize`
+
+error: aborting due to 23 previous errors
+
diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.rs b/tests/ui/fn_to_numeric_cast_with_truncation.rs
new file mode 100644
index 00000000000..82bbaec201f
--- /dev/null
+++ b/tests/ui/fn_to_numeric_cast_with_truncation.rs
@@ -0,0 +1,23 @@
+#![feature(tool_lints)]
+
+#![warn(clippy::fn_to_numeric_cast_with_truncation)]
+#![allow(clippy::fn_to_numeric_cast)]
+
+fn foo() -> String { String::new() }
+
+fn test_fn_to_numeric_cast_with_truncation() {
+    let _ = foo as i8;
+    let _ = foo as i16;
+    let _ = foo as i32;
+    let _ = foo as u8;
+    let _ = foo as u16;
+    let _ = foo as u32;
+
+    // TODO: Is it bad to have these tests?
+    // Running the tests on a different architechture will
+    // produce different results
+    let _ = foo as u64;
+    let _ = foo as i64;
+}
+
+fn main() {}
diff --git a/tests/ui/fn_to_numeric_cast_with_truncation.stderr b/tests/ui/fn_to_numeric_cast_with_truncation.stderr
new file mode 100644
index 00000000000..cae4b6fbd40
--- /dev/null
+++ b/tests/ui/fn_to_numeric_cast_with_truncation.stderr
@@ -0,0 +1,40 @@
+error: casting function pointer `foo` to `i8`, which truncates the value
+ --> $DIR/fn_to_numeric_cast_with_truncation.rs:9:13
+  |
+9 |     let _ = foo as i8;
+  |             ^^^^^^^^^ help: try: `foo as usize`
+  |
+  = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings`
+
+error: casting function pointer `foo` to `i16`, which truncates the value
+  --> $DIR/fn_to_numeric_cast_with_truncation.rs:10:13
+   |
+10 |     let _ = foo as i16;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `i32`, which truncates the value
+  --> $DIR/fn_to_numeric_cast_with_truncation.rs:11:13
+   |
+11 |     let _ = foo as i32;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u8`, which truncates the value
+  --> $DIR/fn_to_numeric_cast_with_truncation.rs:12:13
+   |
+12 |     let _ = foo as u8;
+   |             ^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u16`, which truncates the value
+  --> $DIR/fn_to_numeric_cast_with_truncation.rs:13:13
+   |
+13 |     let _ = foo as u16;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: casting function pointer `foo` to `u32`, which truncates the value
+  --> $DIR/fn_to_numeric_cast_with_truncation.rs:14:13
+   |
+14 |     let _ = foo as u32;
+   |             ^^^^^^^^^^ help: try: `foo as usize`
+
+error: aborting due to 6 previous errors
+