about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJason Newcomb <jsnewcomb@pm.me>2021-05-27 15:16:26 -0400
committerJason Newcomb <jsnewcomb@pm.me>2021-05-27 22:44:08 -0400
commit4ba6afd1922b679eb533b8523f6e47a0da152afb (patch)
tree59815e5a6f2bfa116a9336c0743091d786292dfe
parent543a8a6aac8b346c75dc69cb5b7945a52f72ffe7 (diff)
downloadrust-4ba6afd1922b679eb533b8523f6e47a0da152afb.tar.gz
rust-4ba6afd1922b679eb533b8523f6e47a0da152afb.zip
Fix ICE in `too_many_lines` due to wrong assumptions on braces.
-rw-r--r--clippy_lints/src/functions/too_many_lines.rs22
-rw-r--r--tests/ui/crashes/auxiliary/ice-7272-aux.rs14
-rw-r--r--tests/ui/crashes/ice-7272.rs12
3 files changed, 42 insertions, 6 deletions
diff --git a/clippy_lints/src/functions/too_many_lines.rs b/clippy_lints/src/functions/too_many_lines.rs
index c02c343dc58..a666fee1a4a 100644
--- a/clippy_lints/src/functions/too_many_lines.rs
+++ b/clippy_lints/src/functions/too_many_lines.rs
@@ -4,7 +4,7 @@ use rustc_middle::lint::in_external_macro;
 use rustc_span::Span;
 
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::snippet;
+use clippy_utils::source::snippet_opt;
 
 use super::TOO_MANY_LINES;
 
@@ -13,15 +13,25 @@ pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'
         return;
     }
 
-    let code_snippet = snippet(cx, body.value.span, "..");
+    let code_snippet = match snippet_opt(cx, body.value.span) {
+        Some(s) => s,
+        _ => return,
+    };
     let mut line_count: u64 = 0;
     let mut in_comment = false;
     let mut code_in_line;
 
-    // Skip the surrounding function decl.
-    let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1);
-    let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len());
-    let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines();
+    let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
+        && code_snippet.as_bytes().first().copied() == Some(b'{')
+        && code_snippet.as_bytes().last().copied() == Some(b'}')
+    {
+        // Removing the braces from the enclosing block
+        &code_snippet[1..code_snippet.len() - 1]
+    } else {
+        &code_snippet
+    }
+    .trim() // Remove leading and trailing blank lines
+    .lines();
 
     for mut line in function_lines {
         code_in_line = false;
diff --git a/tests/ui/crashes/auxiliary/ice-7272-aux.rs b/tests/ui/crashes/auxiliary/ice-7272-aux.rs
new file mode 100644
index 00000000000..780797e3c6a
--- /dev/null
+++ b/tests/ui/crashes/auxiliary/ice-7272-aux.rs
@@ -0,0 +1,14 @@
+pub fn warn<T>(_: T) {}
+
+macro_rules! define_macro {
+    ($d:tt $lower:ident $upper:ident) => {
+        #[macro_export]
+        macro_rules! $upper {
+            ($arg:tt) => {
+                $crate::$lower($arg)
+            };
+        }
+    };
+}
+
+define_macro! {$ warn  WARNING}
diff --git a/tests/ui/crashes/ice-7272.rs b/tests/ui/crashes/ice-7272.rs
new file mode 100644
index 00000000000..57ab6ca14f8
--- /dev/null
+++ b/tests/ui/crashes/ice-7272.rs
@@ -0,0 +1,12 @@
+// aux-build:ice-7272-aux.rs
+
+#![allow(clippy::no_effect)]
+
+extern crate ice_7272_aux;
+
+use ice_7272_aux::*;
+
+pub fn main() {
+    || WARNING!("Style changed!");
+    || "}{";
+}