about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2021-02-14 00:51:38 -0700
committerMichael Howell <michael@notriddle.com>2021-02-23 12:03:44 -0700
commitde6f1b82782cc8679e688ba4de3b35cc476a88c6 (patch)
treeba31e5d8b0b75cc63faa634d85a432654a6b27bd
parent019610754363d1d92a8d0f364d2c0909d6f53dfd (diff)
downloadrust-de6f1b82782cc8679e688ba4de3b35cc476a88c6.tar.gz
rust-de6f1b82782cc8679e688ba4de3b35cc476a88c6.zip
Do not consider using a semicolon inside of a different-crate macro
Fixes #81943
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs8
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs6
-rw-r--r--src/test/ui/typeck/auxiliary/issue-81943-lib.rs7
-rw-r--r--src/test/ui/typeck/issue-81943.rs13
-rw-r--r--src/test/ui/typeck/issue-81943.stderr51
5 files changed, 83 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 159c97d8bfa..792836f6665 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -42,6 +42,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{Coercion, InferOk, InferResult};
+use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
 };
@@ -1448,7 +1449,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 expected.is_unit(),
                 pointing_at_return_type,
             ) {
-                if cond_expr.span.desugaring_kind().is_none() {
+                // If the block is from an external macro, then do not suggest
+                // adding a semicolon, because there's nowhere to put it.
+                // See issue #81943.
+                if cond_expr.span.desugaring_kind().is_none()
+                    && !in_external_macro(fcx.tcx.sess, cond_expr.span)
+                {
                     err.span_label(cond_expr.span, "expected this to be `()`");
                     if expr.can_have_side_effects() {
                         fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 416b75d9e2e..1f50ad5779e 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -10,6 +10,7 @@ use rustc_hir::def::{CtorOf, DefKind};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, ItemKind, Node};
 use rustc_infer::infer;
+use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::kw;
 
@@ -44,7 +45,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         blk_id: hir::HirId,
     ) -> bool {
         let expr = expr.peel_drop_temps();
-        if expr.can_have_side_effects() {
+        // If the expression is from an external macro, then do not suggest
+        // adding a semicolon, because there's nowhere to put it.
+        // See issue #81943.
+        if expr.can_have_side_effects() && !in_external_macro(self.tcx.sess, cause_span) {
             self.suggest_missing_semicolon(err, expr, expected, cause_span);
         }
         let mut pointing_at_return_type = false;
diff --git a/src/test/ui/typeck/auxiliary/issue-81943-lib.rs b/src/test/ui/typeck/auxiliary/issue-81943-lib.rs
new file mode 100644
index 00000000000..521c54f8996
--- /dev/null
+++ b/src/test/ui/typeck/auxiliary/issue-81943-lib.rs
@@ -0,0 +1,7 @@
+pub fn g(t: i32) -> i32 { t }
+// This function imitates `dbg!` so that future changes
+// to its macro definition won't make this test a dud.
+#[macro_export]
+macro_rules! d {
+  ($e:expr) => { match $e { x => { $crate::g(x) } } }
+}
diff --git a/src/test/ui/typeck/issue-81943.rs b/src/test/ui/typeck/issue-81943.rs
new file mode 100644
index 00000000000..18f5970a350
--- /dev/null
+++ b/src/test/ui/typeck/issue-81943.rs
@@ -0,0 +1,13 @@
+// aux-build:issue-81943-lib.rs
+extern crate issue_81943_lib as lib;
+
+fn f<F: Fn(i32)>(f: F) { f(0); }
+fn g(t: i32) -> i32 { t }
+fn main() {
+  f(|x| lib::d!(x)); //~ERROR
+  f(|x| match x { tmp => { g(tmp) } }); //~ERROR
+  macro_rules! d {
+    ($e:expr) => { match $e { x => { g(x) } } } //~ERROR
+  }
+  f(|x| d!(x));
+}
diff --git a/src/test/ui/typeck/issue-81943.stderr b/src/test/ui/typeck/issue-81943.stderr
new file mode 100644
index 00000000000..a30facfeb6d
--- /dev/null
+++ b/src/test/ui/typeck/issue-81943.stderr
@@ -0,0 +1,51 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-81943.rs:7:9
+   |
+LL |   f(|x| lib::d!(x));
+   |         ^^^^^^^^^^ expected `()`, found `i32`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/issue-81943.rs:8:28
+   |
+LL |   f(|x| match x { tmp => { g(tmp) } });
+   |         -------------------^^^^^^----
+   |         |                  |
+   |         |                  expected `()`, found `i32`
+   |         expected this to be `()`
+   |
+help: consider using a semicolon here
+   |
+LL |   f(|x| match x { tmp => { g(tmp); } });
+   |                                  ^
+help: consider using a semicolon here
+   |
+LL |   f(|x| match x { tmp => { g(tmp) } };);
+   |                                      ^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-81943.rs:10:38
+   |
+LL |     ($e:expr) => { match $e { x => { g(x) } } }
+   |                    ------------------^^^^----
+   |                    |                 |
+   |                    |                 expected `()`, found `i32`
+   |                    expected this to be `()`
+LL |   }
+LL |   f(|x| d!(x));
+   |         ----- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider using a semicolon here
+   |
+LL |     ($e:expr) => { match $e { x => { g(x); } } }
+   |                                          ^
+help: consider using a semicolon here
+   |
+LL |     ($e:expr) => { match $e { x => { g(x) } }; }
+   |                                              ^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.