about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-03-18 23:01:42 +0100
committerMatthias Krüger <matthias.krueger@famsik.de>2021-03-18 23:47:21 +0100
commitb42ec5e04d51e2fa16a689ce61128533559f09ff (patch)
treef4559e730cf935b79cad288e44a8842139103f78
parent36aee1c52663472870d2fe43658b27a74e1e6f9a (diff)
downloadrust-b42ec5e04d51e2fa16a689ce61128533559f09ff.tar.gz
rust-b42ec5e04d51e2fa16a689ce61128533559f09ff.zip
needless_question_mark: don't lint if Some(..) is inside a macro def and the ? is not.
The suggestion would fail to apply.

Fixes #6921

changelog: needless_question_mark: don't lint if Some(..) is inside a macro def and the ? is not.
-rw-r--r--clippy_lints/src/needless_question_mark.rs7
-rw-r--r--tests/ui/needless_question_mark.fixed25
-rw-r--r--tests/ui/needless_question_mark.rs25
-rw-r--r--tests/ui/needless_question_mark.stderr13
4 files changed, 68 insertions, 2 deletions
diff --git a/clippy_lints/src/needless_question_mark.rs b/clippy_lints/src/needless_question_mark.rs
index 99e85e6683c..9852633b734 100644
--- a/clippy_lints/src/needless_question_mark.rs
+++ b/clippy_lints/src/needless_question_mark.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_ok_ctor, is_some_ctor, meets_msrv};
+use clippy_utils::{differing_macro_contexts, is_ok_ctor, is_some_ctor, meets_msrv};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Body, Expr, ExprKind, LangItem, MatchSource, QPath};
@@ -173,6 +173,11 @@ fn is_some_or_ok_call<'a>(
             // question mark operator
             let inner_expr = &args[0];
 
+            // if the inner expr is inside macro but the outer one is not, do not lint (#6921)
+            if  differing_macro_contexts(expr.span, inner_expr.span) {
+                return None;
+            }
+
             let inner_ty = cx.typeck_results().expr_ty(inner_expr);
             let outer_ty = cx.typeck_results().expr_ty(expr);
 
diff --git a/tests/ui/needless_question_mark.fixed b/tests/ui/needless_question_mark.fixed
index 71fb3565224..fd8433870bb 100644
--- a/tests/ui/needless_question_mark.fixed
+++ b/tests/ui/needless_question_mark.fixed
@@ -167,3 +167,28 @@ mod question_mark_both {
         needless_question_mark_result();
     }
 }
+
+// #6921 if a macro wraps an expr in Some(  ) and the ? is in the macro use,
+// the suggestion fails to apply; do not lint
+macro_rules! some_in_macro {
+    ($expr:expr) => {
+        || -> _ { Some($expr) }()
+    };
+}
+
+pub fn test1() {
+    let x = Some(3);
+    let _x = some_in_macro!(x?);
+}
+
+// this one is ok because both the ? and the Some are both inside the macro def
+macro_rules! some_and_qmark_in_macro {
+    ($expr:expr) => {
+        || -> Option<_> { Some($expr) }()
+    };
+}
+
+pub fn test2() {
+    let x = Some(3);
+    let _x = some_and_qmark_in_macro!(x?);
+}
diff --git a/tests/ui/needless_question_mark.rs b/tests/ui/needless_question_mark.rs
index e31f6f48fa7..36d45ac7e03 100644
--- a/tests/ui/needless_question_mark.rs
+++ b/tests/ui/needless_question_mark.rs
@@ -167,3 +167,28 @@ mod question_mark_both {
         needless_question_mark_result();
     }
 }
+
+// #6921 if a macro wraps an expr in Some(  ) and the ? is in the macro use,
+// the suggestion fails to apply; do not lint
+macro_rules! some_in_macro {
+    ($expr:expr) => {
+        || -> _ { Some($expr) }()
+    };
+}
+
+pub fn test1() {
+    let x = Some(3);
+    let _x = some_in_macro!(x?);
+}
+
+// this one is ok because both the ? and the Some are both inside the macro def
+macro_rules! some_and_qmark_in_macro {
+    ($expr:expr) => {
+        || -> Option<_> { Some(Some($expr)?) }()
+    };
+}
+
+pub fn test2() {
+    let x = Some(3);
+    let _x = some_and_qmark_in_macro!(x?);
+}
diff --git a/tests/ui/needless_question_mark.stderr b/tests/ui/needless_question_mark.stderr
index 983c56031d8..7cbf1e505ad 100644
--- a/tests/ui/needless_question_mark.stderr
+++ b/tests/ui/needless_question_mark.stderr
@@ -84,5 +84,16 @@ error: question mark operator is useless here
 LL |         Ok(to.magic?) // should be triggered
    |         ^^^^^^^^^^^^^ help: try: `to.magic`
 
-error: aborting due to 14 previous errors
+error: question mark operator is useless here
+  --> $DIR/needless_question_mark.rs:187:27
+   |
+LL |         || -> Option<_> { Some(Some($expr)?) }()
+   |                           ^^^^^^^^^^^^^^^^^^ help: try: `Some($expr)`
+...
+LL |     let _x = some_and_qmark_in_macro!(x?);
+   |              ---------------------------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 15 previous errors