From de6f1b82782cc8679e688ba4de3b35cc476a88c6 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 14 Feb 2021 00:51:38 -0700 Subject: [PATCH] Do not consider using a semicolon inside of a different-crate macro Fixes #81943 --- compiler/rustc_typeck/src/check/coercion.rs | 8 ++- .../src/check/fn_ctxt/suggestions.rs | 6 ++- .../ui/typeck/auxiliary/issue-81943-lib.rs | 7 +++ src/test/ui/typeck/issue-81943.rs | 13 +++++ src/test/ui/typeck/issue-81943.stderr | 51 +++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/typeck/auxiliary/issue-81943-lib.rs create mode 100644 src/test/ui/typeck/issue-81943.rs create mode 100644 src/test/ui/typeck/issue-81943.stderr diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 159c97d8bfaa9..792836f666555 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 416b75d9e2e0c..1f50ad5779e0f 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 0000000000000..521c54f899670 --- /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 0000000000000..18f5970a350a2 --- /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: 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 0000000000000..a30facfeb6daa --- /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`.