From 4ba6afd1922b679eb533b8523f6e47a0da152afb Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Thu, 27 May 2021 15:16:26 -0400 Subject: [PATCH] Fix ICE in `too_many_lines` due to wrong assumptions on braces. --- clippy_lints/src/functions/too_many_lines.rs | 22 ++++++++++++++------ tests/ui/crashes/auxiliary/ice-7272-aux.rs | 14 +++++++++++++ tests/ui/crashes/ice-7272.rs | 12 +++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 tests/ui/crashes/auxiliary/ice-7272-aux.rs create mode 100644 tests/ui/crashes/ice-7272.rs 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) {} + +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!"); + || "}{"; +}