Auto merge of #84198 - mlodato517:patch-1, r=jyn514

Fix small typo in Drop documentation
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 04d0686..c8688fa 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1094,7 +1094,7 @@
     //   only place where we have access to the compiler `Session`.
     // - LLVM work can be done on any thread.
     // - Codegen can only happen on the main thread.
-    // - Each thread doing substantial work most be in possession of a `Token`
+    // - Each thread doing substantial work must be in possession of a `Token`
     //   from the `Jobserver`.
     // - The compiler process always holds one `Token`. Any additional `Tokens`
     //   have to be requested from the `Jobserver`.
@@ -1146,7 +1146,7 @@
     // if possible. These two goals are at odds with each other: If memory
     // consumption were not an issue, we could just let the main thread produce
     // LLVM WorkItems at full speed, assuring maximal utilization of
-    // Tokens/LLVM worker threads. However, since codegen usual is faster
+    // Tokens/LLVM worker threads. However, since codegen is usually faster
     // than LLVM processing, the queue of LLVM WorkItems would fill up and each
     // WorkItem potentially holds on to a substantial amount of memory.
     //
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index c4acaef..7f9e459 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 //! Lints in the Rust compiler.
 //!
 //! This contains lints which can feasibly be implemented as their own
@@ -2964,3 +2966,88 @@
         }
     }
 }
+
+declare_lint! {
+    /// The `deref_nullptr` lint detects when an null pointer is dereferenced,
+    /// which causes [undefined behavior].
+    ///
+    /// ### Example
+    ///
+    /// ```rust,no_run
+    /// # #![allow(unused)]
+    /// use std::ptr;
+    /// unsafe {
+    ///     let x = &*ptr::null::<i32>();
+    ///     let x = ptr::addr_of!(*ptr::null::<i32>());
+    ///     let x = *(0 as *const i32);
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Dereferencing a null pointer causes [undefined behavior] even as a place expression,
+    /// like `&*(0 as *const i32)` or `addr_of!(*(0 as *const i32))`.
+    ///
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    pub DEREF_NULLPTR,
+    Warn,
+    "detects when an null pointer is dereferenced"
+}
+
+declare_lint_pass!(DerefNullPtr => [DEREF_NULLPTR]);
+
+impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
+        /// test if expression is a null ptr
+        fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+            match &expr.kind {
+                rustc_hir::ExprKind::Cast(ref expr, ref ty) => {
+                    if let rustc_hir::TyKind::Ptr(_) = ty.kind {
+                        return is_zero(expr) || is_null_ptr(cx, expr);
+                    }
+                }
+                // check for call to `core::ptr::null` or `core::ptr::null_mut`
+                rustc_hir::ExprKind::Call(ref path, _) => {
+                    if let rustc_hir::ExprKind::Path(ref qpath) = path.kind {
+                        if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() {
+                            return cx.tcx.is_diagnostic_item(sym::ptr_null, def_id)
+                                || cx.tcx.is_diagnostic_item(sym::ptr_null_mut, def_id);
+                        }
+                    }
+                }
+                _ => {}
+            }
+            false
+        }
+
+        /// test if experssion is the literal `0`
+        fn is_zero(expr: &hir::Expr<'_>) -> bool {
+            match &expr.kind {
+                rustc_hir::ExprKind::Lit(ref lit) => {
+                    if let LitKind::Int(a, _) = lit.node {
+                        return a == 0;
+                    }
+                }
+                _ => {}
+            }
+            false
+        }
+
+        if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind {
+            if let rustc_hir::UnOp::Deref = un_op {
+                if is_null_ptr(cx, expr_deref) {
+                    cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
+                        let mut err = lint.build("dereferencing a null pointer");
+                        err.span_label(
+                            expr.span,
+                            "this code causes undefined behavior when executed",
+                        );
+                        err.emit();
+                    });
+                }
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index e2724b5..2f46969 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -206,6 +206,7 @@
                 UnreachablePub: UnreachablePub,
                 ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
                 InvalidValue: InvalidValue,
+                DerefNullPtr: DerefNullPtr,
             ]
         );
     };
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 4b97c8b..ed95a56 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -930,15 +930,38 @@
         }
 
         let frame = &self.token_cursor.frame;
-        match frame.tree_cursor.look_ahead(dist - 1) {
-            Some(tree) => match tree {
-                TokenTree::Token(token) => looker(token),
-                TokenTree::Delimited(dspan, delim, _) => {
-                    looker(&Token::new(token::OpenDelim(*delim), dspan.open))
-                }
-            },
-            None => looker(&Token::new(token::CloseDelim(frame.delim), frame.span.close)),
+        if frame.delim != DelimToken::NoDelim {
+            let all_normal = (0..dist).all(|i| {
+                let token = frame.tree_cursor.look_ahead(i);
+                !matches!(token, Some(TokenTree::Delimited(_, DelimToken::NoDelim, _)))
+            });
+            if all_normal {
+                return match frame.tree_cursor.look_ahead(dist - 1) {
+                    Some(tree) => match tree {
+                        TokenTree::Token(token) => looker(token),
+                        TokenTree::Delimited(dspan, delim, _) => {
+                            looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+                        }
+                    },
+                    None => looker(&Token::new(token::CloseDelim(frame.delim), frame.span.close)),
+                };
+            }
         }
+
+        let mut cursor = self.token_cursor.clone();
+        let mut i = 0;
+        let mut token = Token::dummy();
+        while i < dist {
+            token = cursor.next().0;
+            if matches!(
+                token.kind,
+                token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim)
+            ) {
+                continue;
+            }
+            i += 1;
+        }
+        return looker(&token);
     }
 
     /// Returns whether any of the given keywords are `dist` tokens ahead of the current one.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ee1d206..42e521a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -900,6 +900,8 @@
         profiler_runtime,
         ptr_guaranteed_eq,
         ptr_guaranteed_ne,
+        ptr_null,
+        ptr_null_mut,
         ptr_offset_from,
         pub_macro_rules,
         pub_restricted,
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 6e20715..ad8696a 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -211,6 +211,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_diagnostic_item = "ptr_null"]
 pub const fn null<T>() -> *const T {
     0 as *const T
 }
@@ -229,6 +230,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 #[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_diagnostic_item = "ptr_null_mut"]
 pub const fn null_mut<T>() -> *mut T {
     0 as *mut T
 }
diff --git a/library/std/src/sys_common/alloc.rs b/library/std/src/sys/common/alloc.rs
similarity index 98%
rename from library/std/src/sys_common/alloc.rs
rename to library/std/src/sys/common/alloc.rs
index 6c1bc0d..2a54e99 100644
--- a/library/std/src/sys_common/alloc.rs
+++ b/library/std/src/sys/common/alloc.rs
@@ -1,5 +1,3 @@
-#![allow(dead_code)]
-
 use crate::alloc::{GlobalAlloc, Layout, System};
 use crate::cmp;
 use crate::ptr;
diff --git a/library/std/src/sys/common/mod.rs b/library/std/src/sys/common/mod.rs
new file mode 100644
index 0000000..ff64d2a
--- /dev/null
+++ b/library/std/src/sys/common/mod.rs
@@ -0,0 +1,13 @@
+// This module contains code that is shared between all platforms, mostly utility or fallback code.
+// This explicitly does not include code that is shared between only a few platforms,
+// such as when reusing an implementation from `unix` or `unsupported`.
+// In those cases the desired code should be included directly using the #[path] attribute,
+// not moved to this module.
+//
+// Currently `sys_common` contains a lot of code that should live in this module,
+// ideally `sys_common` would only contain platform-independent abstractions on top of `sys`.
+// Progress on this is tracked in #84187.
+
+#![allow(dead_code)]
+
+pub mod alloc;
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 9b35939..50c2660 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -22,6 +22,8 @@
 
 #![allow(missing_debug_implementations)]
 
+mod common;
+
 cfg_if::cfg_if! {
     if #[cfg(target_os = "vxworks")] {
         mod vxworks;
diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs
index 964abe8..1b71905 100644
--- a/library/std/src/sys/unix/alloc.rs
+++ b/library/std/src/sys/unix/alloc.rs
@@ -1,6 +1,6 @@
 use crate::alloc::{GlobalAlloc, Layout, System};
 use crate::ptr;
-use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
+use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};
 
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
 unsafe impl GlobalAlloc for System {
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 4a077e2..ce2c4e8 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -223,7 +223,7 @@
 
 impl fmt::Display for JoinPathsError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "path segment contains separator `{}`", PATH_SEPARATOR)
+        write!(f, "path segment contains separator `{}`", char::from(PATH_SEPARATOR))
     }
 }
 
diff --git a/library/std/src/sys/windows/alloc.rs b/library/std/src/sys/windows/alloc.rs
index af93cd7..2fe71f9 100644
--- a/library/std/src/sys/windows/alloc.rs
+++ b/library/std/src/sys/windows/alloc.rs
@@ -5,7 +5,7 @@
 use crate::ptr;
 use crate::sync::atomic::{AtomicPtr, Ordering};
 use crate::sys::c;
-use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
+use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};
 
 #[cfg(test)]
 mod tests;
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 660f0e0..23a3a0e 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -8,9 +8,11 @@
 //! rest of `std` is complex, with dependencies going in all
 //! directions: `std` depending on `sys_common`, `sys_common`
 //! depending on `sys`, and `sys` depending on `sys_common` and `std`.
-//! Ideally `sys_common` would be split into two and the dependencies
-//! between them all would form a dag, facilitating the extraction of
-//! `std::sys` from the standard library.
+//! This is because `sys_common` not only contains platform-independent code,
+//! but also code that is shared between the different platforms in `sys`.
+//! Ideally all that shared code should be moved to `sys::common`,
+//! and the dependencies between `std`, `sys_common` and `sys` all would form a dag.
+//! Progress on this is tracked in #84187.
 
 #![allow(missing_docs)]
 #![allow(missing_debug_implementations)]
@@ -46,7 +48,6 @@
     };
 }
 
-pub mod alloc;
 pub mod at_exit_imp;
 pub mod backtrace;
 pub mod bytestring;
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index d3f2ace..569c339 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit d3f2ace94d51610cf3e3c265705bb8416d37f8e4
+Subproject commit 569c3391f5c0cc43433bc77831d17f8ff4d76602
diff --git a/src/doc/nomicon b/src/doc/nomicon
index 6fe4769..8551afb 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit 6fe476943afd53a9a6e91f38a6ea7bb48811d8ff
+Subproject commit 8551afbb2ca6f5ea37fe58380318b209785e4e02
diff --git a/src/doc/reference b/src/doc/reference
index fd97729..e1abb17 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit fd97729e2d82f8b08d68a31c9bfdf0c37a7fd542
+Subproject commit e1abb17cd94cd5a8a374b48e1bc8134a2208ed48
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 29d91f5..c80f0b0 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 29d91f591c90dd18fdca6d23f1a9caf9c139d0d7
+Subproject commit c80f0b09fc15b9251825343be910c08531938ab2
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index 0687daa..a9bd2bb 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit 0687daac28939c476df51778f5a1d1aff1a3fddf
+Subproject commit a9bd2bbf31e4f92b5d3d8e80b22839d0cc7a2022
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 6342110..4ce7c70 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1972,6 +1972,10 @@
         if let Some(sp) = sp {
             diag.span_label(sp, "contains invalid anchor");
         }
+        if let AnchorFailure::RustdocAnchorConflict(Res::Primitive(_)) = failure {
+            diag.note("this restriction may be lifted in a future release");
+            diag.note("see https://github.com/rust-lang/rust/issues/83083 for more information");
+        }
     });
 }
 
diff --git a/src/test/rustdoc-ui/intra-doc/anchors.stderr b/src/test/rustdoc-ui/intra-doc/anchors.stderr
index 787a68e..42a8832 100644
--- a/src/test/rustdoc-ui/intra-doc/anchors.stderr
+++ b/src/test/rustdoc-ui/intra-doc/anchors.stderr
@@ -9,6 +9,8 @@
    |
 LL | #![deny(rustdoc::broken_intra_doc_links)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this restriction may be lifted in a future release
+   = note: see https://github.com/rust-lang/rust/issues/83083 for more information
 
 error: `Foo::f#hola` contains an anchor, but links to fields are already anchored
   --> $DIR/anchors.rs:25:15
@@ -33,6 +35,9 @@
    |
 LL | /// [u32#hello]
    |      ^^^^^^^^^ contains invalid anchor
+   |
+   = note: this restriction may be lifted in a future release
+   = note: see https://github.com/rust-lang/rust/issues/83083 for more information
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/cleanup-shortcircuit.rs b/src/test/ui/cleanup-shortcircuit.rs
index 4f5197a..fe867ce 100644
--- a/src/test/ui/cleanup-shortcircuit.rs
+++ b/src/test/ui/cleanup-shortcircuit.rs
@@ -3,6 +3,9 @@
 
 // pretty-expanded FIXME #23616
 
+#![allow(deref_nullptr)]
+
+
 use std::env;
 
 pub fn main() {
diff --git a/src/test/ui/lint/lint-deref-nullptr.rs b/src/test/ui/lint/lint-deref-nullptr.rs
new file mode 100644
index 0000000..d052dbd
--- /dev/null
+++ b/src/test/ui/lint/lint-deref-nullptr.rs
@@ -0,0 +1,38 @@
+// test the deref_nullptr lint
+
+#![deny(deref_nullptr)]
+
+use std::ptr;
+
+struct Struct {
+    field: u8,
+}
+
+fn f() {
+    unsafe {
+        let a = 1;
+        let ub = *(a as *const i32);
+        let ub = *(0 as *const i32);
+        //~^ ERROR dereferencing a null pointer
+        let ub = *ptr::null::<i32>();
+        //~^ ERROR dereferencing a null pointer
+        let ub = *ptr::null_mut::<i32>();
+        //~^ ERROR dereferencing a null pointer
+        let ub = *(ptr::null::<i16>() as *const i32);
+        //~^ ERROR dereferencing a null pointer
+        let ub = *(ptr::null::<i16>() as *mut i32 as *mut usize as *const u8);
+        //~^ ERROR dereferencing a null pointer
+        let ub = &*ptr::null::<i32>();
+        //~^ ERROR dereferencing a null pointer
+        let ub = &*ptr::null_mut::<i32>();
+        //~^ ERROR dereferencing a null pointer
+        ptr::addr_of!(*ptr::null::<i32>());
+        //~^ ERROR dereferencing a null pointer
+        ptr::addr_of_mut!(*ptr::null_mut::<i32>());
+        //~^ ERROR dereferencing a null pointer
+        let offset = ptr::addr_of!((*ptr::null::<Struct>()).field);
+        //~^ ERROR dereferencing a null pointer
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-deref-nullptr.stderr b/src/test/ui/lint/lint-deref-nullptr.stderr
new file mode 100644
index 0000000..c6f432e
--- /dev/null
+++ b/src/test/ui/lint/lint-deref-nullptr.stderr
@@ -0,0 +1,68 @@
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:15:18
+   |
+LL |         let ub = *(0 as *const i32);
+   |                  ^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+note: the lint level is defined here
+  --> $DIR/lint-deref-nullptr.rs:3:9
+   |
+LL | #![deny(deref_nullptr)]
+   |         ^^^^^^^^^^^^^
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:17:18
+   |
+LL |         let ub = *ptr::null::<i32>();
+   |                  ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:19:18
+   |
+LL |         let ub = *ptr::null_mut::<i32>();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:21:18
+   |
+LL |         let ub = *(ptr::null::<i16>() as *const i32);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:23:18
+   |
+LL |         let ub = *(ptr::null::<i16>() as *mut i32 as *mut usize as *const u8);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:25:19
+   |
+LL |         let ub = &*ptr::null::<i32>();
+   |                   ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:27:19
+   |
+LL |         let ub = &*ptr::null_mut::<i32>();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:29:23
+   |
+LL |         ptr::addr_of!(*ptr::null::<i32>());
+   |                       ^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:31:27
+   |
+LL |         ptr::addr_of_mut!(*ptr::null_mut::<i32>());
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: dereferencing a null pointer
+  --> $DIR/lint-deref-nullptr.rs:33:36
+   |
+LL |         let offset = ptr::addr_of!((*ptr::null::<Struct>()).field);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs
new file mode 100644
index 0000000..f5a97ec
--- /dev/null
+++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.rs
@@ -0,0 +1,20 @@
+// edition:2021
+#![allow(unused_macros)]
+macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
+macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
+macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok
+macro_rules! match_any {
+    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
+        match $expr {
+            $(
+                $( $pat => $expr_arm, )+
+            )+
+        }
+    };
+}
+
+fn main() {
+    let result: Result<i64, i32> = Err(42);
+    let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
+    assert_eq!(int, 42);
+}
diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr
new file mode 100644
index 0000000..a5987a2
--- /dev/null
+++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr
@@ -0,0 +1,26 @@
+error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
+  --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:3:28
+   |
+LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
+   |                            ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+
+error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
+  --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32
+   |
+LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
+   |                                ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+
+error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
+  --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36
+   |
+LL |     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
+   |                                    ^ not allowed after `pat` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs
new file mode 100644
index 0000000..54bd13d
--- /dev/null
+++ b/src/test/ui/macros/macro-pat-pattern-followed-by-or.rs
@@ -0,0 +1,20 @@
+// run-pass
+#![allow(unused_macros)]
+macro_rules! foo { ($x:pat | $y:pat) => {} } // should be ok
+macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } // should be ok
+macro_rules! qux { ($x:pat, $y:pat) => {} } // should be ok
+macro_rules! match_any {
+    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { // should be ok
+        match $expr {
+            $(
+                $( $pat => $expr_arm, )+
+            )+
+        }
+    };
+}
+
+fn main() {
+    let result: Result<i64, i32> = Err(42);
+    let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
+    assert_eq!(int, 42);
+}
diff --git a/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs
new file mode 100644
index 0000000..edd3f3e
--- /dev/null
+++ b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.rs
@@ -0,0 +1,21 @@
+#![feature(edition_macro_pats)]
+#![allow(unused_macros)]
+macro_rules! foo { ($x:pat2021 | $y:pat2021) => {} } //~ ERROR `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments
+macro_rules! baz { ($x:pat2015 | $y:pat2015) => {} } // should be ok
+macro_rules! qux { ($x:pat2015 | $y:pat2021) => {} } // should be ok
+macro_rules! ogg { ($x:pat2021 | $y:pat2015) => {} } //~ ERROR `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments
+macro_rules! match_any {
+    ( $expr:expr , $( $( $pat:pat2021 )|+ => $expr_arm:pat2021 ),+ ) => { //~ ERROR  `$pat:pat2021` may be followed by `|`, which is not allowed for `pat2021` fragments
+        match $expr {
+            $(
+                $( $pat => $expr_arm, )+
+            )+
+        }
+    };
+}
+
+fn main() {
+    let result: Result<i64, i32> = Err(42);
+    let int: i64 = match_any!(result, Ok(i) | Err(i) => i.into());
+    assert_eq!(int, 42);
+}
diff --git a/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr
new file mode 100644
index 0000000..fe0b40c
--- /dev/null
+++ b/src/test/ui/macros/macro-pat2021-pattern-followed-by-or.stderr
@@ -0,0 +1,26 @@
+error: `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments
+  --> $DIR/macro-pat2021-pattern-followed-by-or.rs:3:32
+   |
+LL | macro_rules! foo { ($x:pat2021 | $y:pat2021) => {} }
+   |                                ^ not allowed after `pat2021` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+
+error: `$x:pat2021` is followed by `|`, which is not allowed for `pat2021` fragments
+  --> $DIR/macro-pat2021-pattern-followed-by-or.rs:6:32
+   |
+LL | macro_rules! ogg { ($x:pat2021 | $y:pat2015) => {} }
+   |                                ^ not allowed after `pat2021` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+
+error: `$pat:pat2021` may be followed by `|`, which is not allowed for `pat2021` fragments
+  --> $DIR/macro-pat2021-pattern-followed-by-or.rs:8:40
+   |
+LL |     ( $expr:expr , $( $( $pat:pat2021 )|+ => $expr_arm:pat2021 ),+ ) => {
+   |                                        ^ not allowed after `pat2021` fragments
+   |
+   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/macros/none-delim-lookahead.rs b/src/test/ui/macros/none-delim-lookahead.rs
new file mode 100644
index 0000000..bf4fddea
--- /dev/null
+++ b/src/test/ui/macros/none-delim-lookahead.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+macro_rules! make_struct {
+    ($name:ident) => {
+        #[derive(Debug)]
+        struct Foo {
+            #[cfg(not(FALSE))]
+            field: fn($name: bool)
+        }
+    }
+}
+
+make_struct!(param_name);
+
+fn main() {}
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
index 19e09a4..7be0613 160000
--- a/src/tools/rust-analyzer
+++ b/src/tools/rust-analyzer
@@ -1 +1 @@
-Subproject commit 19e09a4a54c75312aeaac04577f2d0e067463ab6
+Subproject commit 7be06139b632ee615fc18af04dd67947e2c794b2