diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 9d0a91c5318..7fcd9b7734c 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -1,5 +1,6 @@
 // error-pattern:cargo-clippy
 
+#![feature(bind_by_move_pattern_guards)] // proposed to be stabilized in Rust v1.39
 #![feature(box_syntax)]
 #![feature(box_patterns)]
 #![feature(never_type)]
diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs
index 47446edac54..a9907ed132d 100644
--- a/clippy_lints/src/misc_early.rs
+++ b/clippy_lints/src/misc_early.rs
@@ -430,15 +430,13 @@ impl EarlyLintPass for MiscEarlyLints {
 
 impl MiscEarlyLints {
     fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
-        // The `line!()` macro is compiler built-in and a special case for these lints.
+        // We test if first character in snippet is a number, because the snippet could be an expansion
+        // from a built-in macro like `line!()` or a proc-macro like `#[wasm_bindgen]`.
+        // Note that this check also covers special case that `line!()` is eagerly expanded by compiler.
+        // See <https://github.com/rust-lang/rust-clippy/issues/4507> for a regression.
+        // FIXME: Find a better way to detect those cases.
         let lit_snip = match snippet_opt(cx, lit.span) {
-            Some(snip) => {
-                // The snip could be empty in case of expand from procedure macro
-                if snip.is_empty() || snip.contains('!') {
-                    return;
-                }
-                snip
-            },
+            Some(snip) if snip.chars().next().map_or(false, |c| c.is_digit(10)) => snip,
             _ => return,
         };
 
diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs
index ddb40dace75..60ffd94e733 100644
--- a/mini-macro/src/lib.rs
+++ b/mini-macro/src/lib.rs
@@ -17,5 +17,8 @@ pub fn mini_macro(_: TokenStream) -> TokenStream {
                 println!("{}", items[i]);
             }
         }
+        fn line_wrapper() {
+            println!("{}", line!());
+        }
     )
 }
diff --git a/tests/ui/unseparated_prefix_literals.fixed b/tests/ui/unseparated_prefix_literals.fixed
index 26bc47257b7..3c422cc4fee 100644
--- a/tests/ui/unseparated_prefix_literals.fixed
+++ b/tests/ui/unseparated_prefix_literals.fixed
@@ -3,6 +3,13 @@
 #![warn(clippy::unseparated_literal_suffix)]
 #![allow(dead_code)]
 
+#[macro_use]
+extern crate clippy_mini_macro_test;
+
+// Test for proc-macro attribute
+#[derive(ClippyMiniMacroTest)]
+struct Foo;
+
 macro_rules! lit_from_macro {
     () => {
         42_usize
diff --git a/tests/ui/unseparated_prefix_literals.rs b/tests/ui/unseparated_prefix_literals.rs
index d710ccd1be2..09608661e0e 100644
--- a/tests/ui/unseparated_prefix_literals.rs
+++ b/tests/ui/unseparated_prefix_literals.rs
@@ -3,6 +3,13 @@
 #![warn(clippy::unseparated_literal_suffix)]
 #![allow(dead_code)]
 
+#[macro_use]
+extern crate clippy_mini_macro_test;
+
+// Test for proc-macro attribute
+#[derive(ClippyMiniMacroTest)]
+struct Foo;
+
 macro_rules! lit_from_macro {
     () => {
         42usize
diff --git a/tests/ui/unseparated_prefix_literals.stderr b/tests/ui/unseparated_prefix_literals.stderr
index 85f1881949e..d353d34fb35 100644
--- a/tests/ui/unseparated_prefix_literals.stderr
+++ b/tests/ui/unseparated_prefix_literals.stderr
@@ -1,5 +1,5 @@
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:16:18
+  --> $DIR/unseparated_prefix_literals.rs:23:18
    |
 LL |     let _fail1 = 1234i32;
    |                  ^^^^^^^ help: add an underscore: `1234_i32`
@@ -7,43 +7,43 @@ LL |     let _fail1 = 1234i32;
    = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:17:18
+  --> $DIR/unseparated_prefix_literals.rs:24:18
    |
 LL |     let _fail2 = 1234u32;
    |                  ^^^^^^^ help: add an underscore: `1234_u32`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:18:18
+  --> $DIR/unseparated_prefix_literals.rs:25:18
    |
 LL |     let _fail3 = 1234isize;
    |                  ^^^^^^^^^ help: add an underscore: `1234_isize`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:19:18
+  --> $DIR/unseparated_prefix_literals.rs:26:18
    |
 LL |     let _fail4 = 1234usize;
    |                  ^^^^^^^^^ help: add an underscore: `1234_usize`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:20:18
+  --> $DIR/unseparated_prefix_literals.rs:27:18
    |
 LL |     let _fail5 = 0x123isize;
    |                  ^^^^^^^^^^ help: add an underscore: `0x123_isize`
 
 error: float type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:24:19
+  --> $DIR/unseparated_prefix_literals.rs:31:19
    |
 LL |     let _failf1 = 1.5f32;
    |                   ^^^^^^ help: add an underscore: `1.5_f32`
 
 error: float type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:25:19
+  --> $DIR/unseparated_prefix_literals.rs:32:19
    |
 LL |     let _failf2 = 1f32;
    |                   ^^^^ help: add an underscore: `1_f32`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:8:9
+  --> $DIR/unseparated_prefix_literals.rs:15:9
    |
 LL |         42usize
    |         ^^^^^^^ help: add an underscore: `42_usize`
@@ -52,7 +52,7 @@ LL |     let _ = lit_from_macro!();
    |             ----------------- in this macro invocation
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:33:16
+  --> $DIR/unseparated_prefix_literals.rs:40:16
    |
 LL |     assert_eq!(4897u32, 32223);
    |                ^^^^^^^ help: add an underscore: `4897_u32`