about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/unused.rs88
-rw-r--r--src/test/ui/lint/unused_parens_multibyte_recovery.rs11
-rw-r--r--src/test/ui/lint/unused_parens_multibyte_recovery.stderr43
3 files changed, 96 insertions, 46 deletions
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index b6cf182916c..4e7ba1c6ce4 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
-use rustc_span::{BytePos, Span, DUMMY_SP};
+use rustc_span::{BytePos, Span};
 
 declare_lint! {
     /// The `unused_must_use` lint detects unused result of a type flagged as
@@ -504,23 +504,23 @@ trait UnusedDelimLint {
             ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
                 let start = block.stmts[0].span;
                 let end = block.stmts[block.stmts.len() - 1].span;
-                if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
-                    (
-                        value.span.with_hi(value.span.lo() + BytePos(1)),
-                        value.span.with_lo(value.span.hi() - BytePos(1)),
-                    )
+                if let Some(start) = start.find_ancestor_inside(value.span)
+                    && let Some(end) = end.find_ancestor_inside(value.span)
+                {
+                    Some((
+                        value.span.with_hi(start.lo()),
+                        value.span.with_lo(end.hi()),
+                    ))
                 } else {
-                    (value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
+                    None
                 }
             }
             ast::ExprKind::Paren(ref expr) => {
-                if value.span.from_expansion() || expr.span.from_expansion() {
-                    (
-                        value.span.with_hi(value.span.lo() + BytePos(1)),
-                        value.span.with_lo(value.span.hi() - BytePos(1)),
-                    )
+                let expr_span = expr.span.find_ancestor_inside(value.span);
+                if let Some(expr_span) = expr_span {
+                    Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
                 } else {
-                    (value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
+                    None
                 }
             }
             _ => return,
@@ -529,36 +529,38 @@ trait UnusedDelimLint {
             left_pos.map_or(false, |s| s >= value.span.lo()),
             right_pos.map_or(false, |s| s <= value.span.hi()),
         );
-        self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
+        self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
     }
 
     fn emit_unused_delims(
         &self,
         cx: &EarlyContext<'_>,
-        spans: (Span, Span),
+        value_span: Span,
+        spans: Option<(Span, Span)>,
         msg: &str,
         keep_space: (bool, bool),
     ) {
-        // FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
-        // properly.
-        if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
-            return;
-        }
-
-        cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
-            let replacement = vec![
-                (spans.0, if keep_space.0 { " ".into() } else { "".into() }),
-                (spans.1, if keep_space.1 { " ".into() } else { "".into() }),
-            ];
-            lint.build(fluent::lint::unused_delim)
-                .set_arg("delim", Self::DELIM_STR)
-                .set_arg("item", msg)
-                .multipart_suggestion(
+        let primary_span = if let Some((lo, hi)) = spans {
+            MultiSpan::from(vec![lo, hi])
+        } else {
+            MultiSpan::from(value_span)
+        };
+        cx.struct_span_lint(self.lint(), primary_span, |lint| {
+            let mut db = lint.build(fluent::lint::unused_delim);
+            db.set_arg("delim", Self::DELIM_STR);
+            db.set_arg("item", msg);
+            if let Some((lo, hi)) = spans {
+                let replacement = vec![
+                    (lo, if keep_space.0 { " ".into() } else { "".into() }),
+                    (hi, if keep_space.1 { " ".into() } else { "".into() }),
+                ];
+                db.multipart_suggestion(
                     fluent::lint::suggestion,
                     replacement,
                     Applicability::MachineApplicable,
-                )
-                .emit();
+                );
+            }
+            db.emit();
         });
     }
 
@@ -766,15 +768,12 @@ impl UnusedParens {
                 // Otherwise proceed with linting.
                 _ => {}
             }
-            let spans = if value.span.from_expansion() || inner.span.from_expansion() {
-                (
-                    value.span.with_hi(value.span.lo() + BytePos(1)),
-                    value.span.with_lo(value.span.hi() - BytePos(1)),
-                )
+            let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
+                Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
             } else {
-                (value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
+                None
             };
-            self.emit_unused_delims(cx, spans, "pattern", (false, false));
+            self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
         }
     }
 }
@@ -879,15 +878,12 @@ impl EarlyLintPass for UnusedParens {
                     );
                 }
                 _ => {
-                    let spans = if ty.span.from_expansion() || r.span.from_expansion() {
-                        (
-                            ty.span.with_hi(ty.span.lo() + BytePos(1)),
-                            ty.span.with_lo(ty.span.hi() - BytePos(1)),
-                        )
+                    let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
+                        Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
                     } else {
-                        (ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
+                        None
                     };
-                    self.emit_unused_delims(cx, spans, "type", (false, false));
+                    self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
                 }
             }
         }
diff --git a/src/test/ui/lint/unused_parens_multibyte_recovery.rs b/src/test/ui/lint/unused_parens_multibyte_recovery.rs
new file mode 100644
index 00000000000..8fcfae22a3d
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_multibyte_recovery.rs
@@ -0,0 +1,11 @@
+// ignore-tidy-trailing-newlines
+//
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: format argument must be a string literal
+//
+// Verify that unused parens lint does not try to create a span
+// which points in the middle of a multibyte character.
+
+fn f(){(print!(á
\ No newline at end of file
diff --git a/src/test/ui/lint/unused_parens_multibyte_recovery.stderr b/src/test/ui/lint/unused_parens_multibyte_recovery.stderr
new file mode 100644
index 00000000000..a0302b17e25
--- /dev/null
+++ b/src/test/ui/lint/unused_parens_multibyte_recovery.stderr
@@ -0,0 +1,43 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/unused_parens_multibyte_recovery.rs:11:17
+   |
+LL | fn f(){(print!(á
+   |       --      - ^
+   |       ||      |
+   |       ||      unclosed delimiter
+   |       |unclosed delimiter
+   |       unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/unused_parens_multibyte_recovery.rs:11:17
+   |
+LL | fn f(){(print!(á
+   |       --      - ^
+   |       ||      |
+   |       ||      unclosed delimiter
+   |       |unclosed delimiter
+   |       unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/unused_parens_multibyte_recovery.rs:11:17
+   |
+LL | fn f(){(print!(á
+   |       --      - ^
+   |       ||      |
+   |       ||      unclosed delimiter
+   |       |unclosed delimiter
+   |       unclosed delimiter
+
+error: format argument must be a string literal
+  --> $DIR/unused_parens_multibyte_recovery.rs:11:16
+   |
+LL | fn f(){(print!(á
+   |                ^
+   |
+help: you might be missing a string literal to format with
+   |
+LL | fn f(){(print!("{}", á
+   |                +++++
+
+error: aborting due to 4 previous errors
+