diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index b9a8d16311c93..56b889fdcdda6 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -32,11 +32,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) {
+        // This suggestion is incorrect for
+        // fn foo() -> bool { match () { () => true } || match () { () => true } }
         err.span_suggestion_short(
             span.shrink_to_hi(),
             "consider using a semicolon here",
             ";",
-            Applicability::MachineApplicable,
+            Applicability::MaybeIncorrect,
         );
     }
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index e0443a697b504..0a948a2810a4e 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -390,20 +390,11 @@ impl<'a> Parser<'a> {
             // want to keep their span info to improve diagnostics in these cases in a later stage.
             (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
             (true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
-            (true, Some(AssocOp::Add)) // `{ 42 } + 42
-            // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
-            // `if x { a } else { b } && if y { c } else { d }`
-            if !self.look_ahead(1, |t| t.is_used_keyword()) => {
-                // These cases are ambiguous and can't be identified in the parser alone.
-                let sp = self.sess.source_map().start_point(self.token.span);
-                self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
-                false
-            }
-            (true, Some(AssocOp::LAnd)) |
-            (true, Some(AssocOp::LOr)) |
-            (true, Some(AssocOp::BitOr)) => {
-                // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
-                // above due to #74233.
+            (true, Some(AssocOp::Add)) | // `{ 42 } + 42` (unary plus)
+            (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
+            (true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure)
+            (true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42`
+            => {
                 // These cases are ambiguous and can't be identified in the parser alone.
                 //
                 // Bitwise AND is left out because guessing intent is hard. We can make
diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed
index 36709eea17c21..b06f62794c4e3 100644
--- a/src/test/ui/parser/expr-as-stmt.fixed
+++ b/src/test/ui/parser/expr-as-stmt.fixed
@@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
     { foo(); } || { true } //~ ERROR E0308
 }
 
+// https://github.com/rust-lang/rust/issues/105179
+fn r#match() -> i32 {
+    (match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
+// https://github.com/rust-lang/rust/issues/102171
+fn r#unsafe() -> i32 {
+    (unsafe { 1 }) + unsafe { 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs
index 92bb972b24020..b39d2b88647c0 100644
--- a/src/test/ui/parser/expr-as-stmt.rs
+++ b/src/test/ui/parser/expr-as-stmt.rs
@@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool {
     { foo() } || { true } //~ ERROR E0308
 }
 
+// https://github.com/rust-lang/rust/issues/105179
+fn r#match() -> i32 {
+    match () { () => 1 } + match () { () => 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
+// https://github.com/rust-lang/rust/issues/102171
+fn r#unsafe() -> i32 {
+    unsafe { 1 } + unsafe { 1 } //~ ERROR expected expression, found `+`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr
index 6da4ac34067e9..18c8b0b7c506b 100644
--- a/src/test/ui/parser/expr-as-stmt.stderr
+++ b/src/test/ui/parser/expr-as-stmt.stderr
@@ -55,6 +55,28 @@ help: parentheses are required to parse this as an expression
 LL |     ({ true }) | { true }
    |     +        +
 
+error: expected expression, found `+`
+  --> $DIR/expr-as-stmt.rs:69:26
+   |
+LL |     match () { () => 1 } + match () { () => 1 }
+   |                          ^ expected expression
+   |
+help: parentheses are required to parse this as an expression
+   |
+LL |     (match () { () => 1 }) + match () { () => 1 }
+   |     +                    +
+
+error: expected expression, found `+`
+  --> $DIR/expr-as-stmt.rs:75:18
+   |
+LL |     unsafe { 1 } + unsafe { 1 }
+   |                  ^ expected expression
+   |
+help: parentheses are required to parse this as an expression
+   |
+LL |     (unsafe { 1 }) + unsafe { 1 }
+   |     +            +
+
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt.rs:64:7
    |
@@ -201,7 +223,26 @@ help: parentheses are required to parse this as an expression
 LL |     ({ true }) || { true }
    |     +        +
 
-error: aborting due to 18 previous errors
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt.rs:69:5
+   |
+LL |     match () { () => 1 } + match () { () => 1 }
+   |     ^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here
+   |     |
+   |     expected `()`, found integer
+
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt.rs:75:14
+   |
+LL |     unsafe { 1 } + unsafe { 1 }
+   |              ^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     unsafe { return 1; } + unsafe { 1 }
+   |              ++++++  +
+
+error: aborting due to 22 previous errors
 
 Some errors have detailed explanations: E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0308`.