about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-02-12 06:54:18 +0000
committerbors <bors@rust-lang.org>2025-02-12 06:54:18 +0000
commit33d92df3e6552a91ace2594eb7a2e1dc0c3e37fb (patch)
treee4d932374c9d0fd20161c427d151e555946c3d9d
parent672e3aaf28ab1e5cbe80b3ff012cd3a8e4ef98af (diff)
parent77a1d6b266fa6254d65fc7cc2a4401bf6426290f (diff)
downloadrust-33d92df3e6552a91ace2594eb7a2e1dc0c3e37fb.tar.gz
rust-33d92df3e6552a91ace2594eb7a2e1dc0c3e37fb.zip
Auto merge of #136905 - matthiaskrgr:rollup-8zwcgta, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #135549 (Document some safety constraints and use more safe wrappers)
 - #135965 (In "specify type" suggestion, skip type params that are already known)
 - #136193 (Implement pattern type ffi checks)
 - #136646 (Add a TyPat in the AST to reuse the generic arg lowering logic)
 - #136874 (Change the issue number for `likely_unlikely` and `cold_path`)
 - #136884 (Lower fn items as ZST valtrees and delay a bug)
 - #136885 (i686-linux-android: increase CPU baseline to Pentium 4 (without an actual change)
 - #136891 (Check sig for errors before checking for unconstrained anonymous lifetime)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast/src/ast.rs23
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs20
-rw-r--r--compiler/rustc_ast/src/visit.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs80
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs24
-rw-r--r--compiler/rustc_builtin_macros/src/pattern_type.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/allocator.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs212
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs58
-rw-r--r--compiler/rustc_lint/messages.ftl3
-rw-r--r--compiler/rustc_lint/src/foreign_modules.rs9
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_lint/src/types.rs148
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs13
-rw-r--r--compiler/rustc_resolve/src/late.rs15
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_linux_android.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs87
-rw-r--r--library/core/src/hint.rs6
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/tools/rustfmt/src/patterns.rs87
-rw-r--r--src/tools/rustfmt/src/spanned.rs2
-rw-r--r--src/tools/rustfmt/src/types.rs16
-rw-r--r--tests/ui/async-await/unconstrained-lifetimes.rs9
-rw-r--r--tests/ui/async-await/unconstrained-lifetimes.stderr9
-rw-r--r--tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs13
-rw-r--r--tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr19
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.stderr4
-rw-r--r--tests/ui/inference/erase-type-params-in-label.stderr8
-rw-r--r--tests/ui/inference/issue-104649.stderr4
-rw-r--r--tests/ui/inference/issue-83606.stderr4
-rw-r--r--tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs10
-rw-r--r--tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr14
-rw-r--r--tests/ui/lint/clashing-extern-fn.rs32
-rw-r--r--tests/ui/lint/clashing-extern-fn.stderr23
-rw-r--r--tests/ui/lint/lint-ctypes-enum.rs1
-rw-r--r--tests/ui/lint/lint-ctypes-enum.stderr49
-rw-r--r--tests/ui/type-inference/or_else-multiple-type-params.stderr4
-rw-r--r--tests/ui/type/pattern_types/assoc_const.default.stderr83
-rw-r--r--tests/ui/type/pattern_types/assoc_const.rs12
-rw-r--r--tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs2
-rw-r--r--tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr11
-rw-r--r--tests/ui/type/pattern_types/const_block.rs2
-rw-r--r--tests/ui/type/pattern_types/const_block.stderr72
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types.rs1
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types.stderr8
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types2.rs2
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr8
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.stdout2
57 files changed, 738 insertions, 556 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index deee3a597ae..29c1d34a125 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2249,7 +2249,7 @@ pub enum TyKind {
     CVarArgs,
     /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
     /// just as part of the type system.
-    Pat(P<Ty>, P<Pat>),
+    Pat(P<Ty>, P<TyPat>),
     /// Sometimes we need a dummy value when no error has occurred.
     Dummy,
     /// Placeholder for a kind that has failed to be defined.
@@ -2277,6 +2277,27 @@ impl TyKind {
     }
 }
 
+/// A pattern type pattern.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct TyPat {
+    pub id: NodeId,
+    pub kind: TyPatKind,
+    pub span: Span,
+    pub tokens: Option<LazyAttrTokenStream>,
+}
+
+/// All the different flavors of pattern that Rust recognizes.
+//
+// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub enum TyPatKind {
+    /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
+    Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>),
+
+    /// Placeholder for a pattern that wasn't syntactically well formed in some way.
+    Err(ErrorGuaranteed),
+}
+
 /// Syntax used to declare a trait object.
 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 #[repr(u8)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index a9961cca583..de9f049704a 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -210,6 +210,10 @@ pub trait MutVisitor: Sized {
         walk_ty(self, t);
     }
 
+    fn visit_ty_pat(&mut self, t: &mut P<TyPat>) {
+        walk_ty_pat(self, t);
+    }
+
     fn visit_lifetime(&mut self, l: &mut Lifetime) {
         walk_lifetime(self, l);
     }
@@ -570,7 +574,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
         TyKind::Paren(ty) => vis.visit_ty(ty),
         TyKind::Pat(ty, pat) => {
             vis.visit_ty(ty);
-            vis.visit_pat(pat);
+            vis.visit_ty_pat(pat);
         }
         TyKind::Path(qself, path) => {
             vis.visit_qself(qself);
@@ -594,6 +598,20 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
     vis.visit_span(span);
 }
 
+pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
+    let TyPat { id, kind, span, tokens } = ty.deref_mut();
+    vis.visit_id(id);
+    match kind {
+        TyPatKind::Range(start, end, _include_end) => {
+            visit_opt(start, |c| vis.visit_anon_const(c));
+            visit_opt(end, |c| vis.visit_anon_const(c));
+        }
+        TyPatKind::Err(_) => {}
+    }
+    visit_lazy_tts(vis, tokens);
+    vis.visit_span(span);
+}
+
 fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
     let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
     visit_safety(vis, safety);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 714b074f930..3242d414595 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -179,6 +179,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result {
         walk_ty(self, t)
     }
+    fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
+        walk_ty_pat(self, t)
+    }
     fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result {
         walk_generic_param(self, param)
     }
@@ -534,7 +537,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
         }
         TyKind::Pat(ty, pat) => {
             try_visit!(visitor.visit_ty(ty));
-            try_visit!(visitor.visit_pat(pat));
+            try_visit!(visitor.visit_ty_pat(pat));
         }
         TyKind::Array(ty, length) => {
             try_visit!(visitor.visit_ty(ty));
@@ -555,6 +558,18 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
     V::Result::output()
 }
 
+pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result {
+    let TyPat { id: _, kind, span: _, tokens: _ } = tp;
+    match kind {
+        TyPatKind::Range(start, end, _include_end) => {
+            visit_opt!(visitor, visit_anon_const, start);
+            visit_opt!(visitor, visit_anon_const, end);
+        }
+        TyPatKind::Err(_) => {}
+    }
+    V::Result::output()
+}
+
 fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result {
     if let Some(qself) = qself {
         let QSelf { ty, path_span: _, position: _ } = &**qself;
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index bb9b2a13185..e1f3afbcf59 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -4,10 +4,10 @@ use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::Res;
 use rustc_middle::span_bug;
 use rustc_span::source_map::{Spanned, respan};
-use rustc_span::{Ident, Span, kw};
+use rustc_span::{Ident, Span};
 
 use super::errors::{
     ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
@@ -430,78 +430,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind })
     }
 
-    pub(crate) fn lower_ty_pat(&mut self, pattern: &Pat) -> &'hir hir::TyPat<'hir> {
+    pub(crate) fn lower_ty_pat(&mut self, pattern: &TyPat) -> &'hir hir::TyPat<'hir> {
         self.arena.alloc(self.lower_ty_pat_mut(pattern))
     }
 
-    fn lower_ty_pat_mut(&mut self, mut pattern: &Pat) -> hir::TyPat<'hir> {
+    fn lower_ty_pat_mut(&mut self, pattern: &TyPat) -> hir::TyPat<'hir> {
         // loop here to avoid recursion
         let pat_hir_id = self.lower_node_id(pattern.id);
-        let node = loop {
-            match &pattern.kind {
-                PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
-                    // FIXME(pattern_types): remove this closure and call `lower_const_arg` instead.
-                    // That requires first modifying the AST to have const args here.
-                    let mut lower_expr = |e: &Expr| -> &_ {
-                        if let ExprKind::Path(None, path) = &e.kind
-                            && let Some(res) = self
-                                .resolver
-                                .get_partial_res(e.id)
-                                .and_then(|partial_res| partial_res.full_res())
-                        {
-                            self.lower_const_path_to_const_arg(path, res, e.id, e.span)
-                        } else {
-                            let node_id = self.next_node_id();
-                            let def_id = self.create_def(
-                                self.current_hir_id_owner.def_id,
-                                node_id,
-                                kw::Empty,
-                                DefKind::AnonConst,
-                                e.span,
-                            );
-                            let hir_id = self.lower_node_id(node_id);
-                            let ac = self.arena.alloc(hir::AnonConst {
-                                def_id,
-                                hir_id,
-                                body: self.lower_const_body(pattern.span, Some(e)),
-                                span: self.lower_span(pattern.span),
-                            });
-                            self.arena.alloc(hir::ConstArg {
-                                hir_id: self.next_id(),
-                                kind: hir::ConstArgKind::Anon(ac),
-                            })
-                        }
-                    };
-                    break hir::TyPatKind::Range(
-                        e1.as_deref().map(|e| lower_expr(e)),
-                        e2.as_deref().map(|e| lower_expr(e)),
-                        self.lower_range_end(end, e2.is_some()),
-                    );
-                }
-                // return inner to be processed in next loop
-                PatKind::Paren(inner) => pattern = inner,
-                PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
-                PatKind::Err(guar) => break hir::TyPatKind::Err(*guar),
-                PatKind::Deref(..)
-                | PatKind::Box(..)
-                | PatKind::Or(..)
-                | PatKind::Struct(..)
-                | PatKind::TupleStruct(..)
-                | PatKind::Tuple(..)
-                | PatKind::Ref(..)
-                | PatKind::Expr(..)
-                | PatKind::Guard(..)
-                | PatKind::Slice(_)
-                | PatKind::Ident(..)
-                | PatKind::Path(..)
-                | PatKind::Wild
-                | PatKind::Never
-                | PatKind::Rest => {
-                    break hir::TyPatKind::Err(
-                        self.dcx().span_err(pattern.span, "pattern not supported in pattern types"),
-                    );
-                }
-            }
+        let node = match &pattern.kind {
+            TyPatKind::Range(e1, e2, Spanned { node: end, .. }) => hir::TyPatKind::Range(
+                e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
+                e2.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
+                self.lower_range_end(end, e2.is_some()),
+            ),
+            TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar),
         };
 
         hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index eeec24e5ea4..0bf5de3ef89 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1148,6 +1148,28 @@ impl<'a> State<'a> {
         }
     }
 
+    pub fn print_ty_pat(&mut self, pat: &ast::TyPat) {
+        match &pat.kind {
+            rustc_ast::TyPatKind::Range(start, end, include_end) => {
+                if let Some(start) = start {
+                    self.print_expr_anon_const(start, &[]);
+                }
+                self.word("..");
+                if let Some(end) = end {
+                    if let RangeEnd::Included(_) = include_end.node {
+                        self.word("=");
+                    }
+                    self.print_expr_anon_const(end, &[]);
+                }
+            }
+            rustc_ast::TyPatKind::Err(_) => {
+                self.popen();
+                self.word("/*ERROR*/");
+                self.pclose();
+            }
+        }
+    }
+
     pub fn print_type(&mut self, ty: &ast::Ty) {
         self.maybe_print_comment(ty.span.lo());
         self.ibox(0);
@@ -1252,7 +1274,7 @@ impl<'a> State<'a> {
             ast::TyKind::Pat(ty, pat) => {
                 self.print_type(ty);
                 self.word(" is ");
-                self.print_pat(pat);
+                self.print_ty_pat(pat);
             }
         }
         self.end();
diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs
index a600a9f316a..a55c7e962d0 100644
--- a/compiler/rustc_builtin_macros/src/pattern_type.rs
+++ b/compiler/rustc_builtin_macros/src/pattern_type.rs
@@ -1,6 +1,6 @@
 use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::{Pat, Ty, ast};
+use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast};
 use rustc_errors::PResult;
 use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
 use rustc_parse::exp;
@@ -21,12 +21,24 @@ pub(crate) fn expand<'cx>(
     ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
 }
 
-fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<Pat>)> {
+fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
     let mut parser = cx.new_parser_from_tts(stream);
 
     let ty = parser.parse_ty()?;
     parser.expect_keyword(exp!(Is))?;
-    let pat = parser.parse_pat_no_top_alt(None, None)?;
+    let pat = parser.parse_pat_no_top_alt(None, None)?.into_inner();
+
+    let kind = match pat.kind {
+        ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
+            start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
+            end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
+            include_end,
+        ),
+        ast::PatKind::Err(guar) => TyPatKind::Err(guar),
+        _ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
+    };
+
+    let pat = P(TyPat { id: pat.id, kind, span: pat.span, tokens: pat.tokens });
 
     Ok((ty, pat))
 }
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 149ded28356..66723cbf882 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -81,13 +81,13 @@ pub(crate) unsafe fn codegen(
         llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
         let val = tcx.sess.opts.unstable_opts.oom.should_panic();
         let llval = llvm::LLVMConstInt(i8, val as u64, False);
-        llvm::LLVMSetInitializer(ll_g, llval);
+        llvm::set_initializer(ll_g, llval);
 
         let name = NO_ALLOC_SHIM_IS_UNSTABLE;
         let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8);
         llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
         let llval = llvm::LLVMConstInt(i8, 0, False);
-        llvm::LLVMSetInitializer(ll_g, llval);
+        llvm::set_initializer(ll_g, llval);
     }
 
     if tcx.sess.opts.debuginfo != DebugInfo::None {
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 33a956e552f..93553f3f364 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -11,7 +11,7 @@ use rustc_codegen_ssa::back::archive::{
 use rustc_session::Session;
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
-use crate::llvm::{self, ArchiveKind};
+use crate::llvm::{self, ArchiveKind, last_error};
 
 /// Helper for adding many files to an archive.
 #[must_use = "must call build() to finish building the archive"]
@@ -169,6 +169,8 @@ impl<'a> LlvmArchiveBuilder<'a> {
             .unwrap_or_else(|kind| self.sess.dcx().emit_fatal(UnknownArchiveKind { kind }));
 
         let mut additions = mem::take(&mut self.additions);
+        // Values in the `members` list below will contain pointers to the strings allocated here.
+        // So they need to get dropped after all elements of `members` get freed.
         let mut strings = Vec::new();
         let mut members = Vec::new();
 
@@ -229,12 +231,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
                 self.sess.target.arch == "arm64ec",
             );
             let ret = if r.into_result().is_err() {
-                let err = llvm::LLVMRustGetLastError();
-                let msg = if err.is_null() {
-                    "failed to write archive".into()
-                } else {
-                    String::from_utf8_lossy(CStr::from_ptr(err).to_bytes())
-                };
+                let msg = last_error().unwrap_or_else(|| "failed to write archive".into());
                 Err(io::Error::new(io::ErrorKind::Other, msg))
             } else {
                 Ok(!members.is_empty())
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index ae4c4d5876e..58933a77e53 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -40,7 +40,7 @@ use crate::errors::{
     WithLlvmError, WriteBytecode,
 };
 use crate::llvm::diagnostic::OptimizationDiagnosticKind::*;
-use crate::llvm::{self, DiagnosticInfo, PassManager};
+use crate::llvm::{self, DiagnosticInfo};
 use crate::type_::Type;
 use crate::{LlvmCodegenBackend, ModuleLlvm, base, common, llvm_util};
 
@@ -54,7 +54,7 @@ pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> Fatal
 fn write_output_file<'ll>(
     dcx: DiagCtxtHandle<'_>,
     target: &'ll llvm::TargetMachine,
-    pm: &llvm::PassManager<'ll>,
+    no_builtins: bool,
     m: &'ll llvm::Module,
     output: &Path,
     dwo_output: Option<&Path>,
@@ -63,16 +63,19 @@ fn write_output_file<'ll>(
     verify_llvm_ir: bool,
 ) -> Result<(), FatalError> {
     debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output);
-    unsafe {
-        let output_c = path_to_c_string(output);
-        let dwo_output_c;
-        let dwo_output_ptr = if let Some(dwo_output) = dwo_output {
-            dwo_output_c = path_to_c_string(dwo_output);
-            dwo_output_c.as_ptr()
-        } else {
-            std::ptr::null()
-        };
-        let result = llvm::LLVMRustWriteOutputFile(
+    let output_c = path_to_c_string(output);
+    let dwo_output_c;
+    let dwo_output_ptr = if let Some(dwo_output) = dwo_output {
+        dwo_output_c = path_to_c_string(dwo_output);
+        dwo_output_c.as_ptr()
+    } else {
+        std::ptr::null()
+    };
+    let result = unsafe {
+        let pm = llvm::LLVMCreatePassManager();
+        llvm::LLVMAddAnalysisPasses(target, pm);
+        llvm::LLVMRustAddLibraryInfo(pm, m, no_builtins);
+        llvm::LLVMRustWriteOutputFile(
             target,
             pm,
             m,
@@ -80,22 +83,22 @@ fn write_output_file<'ll>(
             dwo_output_ptr,
             file_type,
             verify_llvm_ir,
-        );
+        )
+    };
 
-        // Record artifact sizes for self-profiling
-        if result == llvm::LLVMRustResult::Success {
-            let artifact_kind = match file_type {
-                llvm::FileType::ObjectFile => "object_file",
-                llvm::FileType::AssemblyFile => "assembly_file",
-            };
-            record_artifact_size(self_profiler_ref, artifact_kind, output);
-            if let Some(dwo_file) = dwo_output {
-                record_artifact_size(self_profiler_ref, "dwo_file", dwo_file);
-            }
+    // Record artifact sizes for self-profiling
+    if result == llvm::LLVMRustResult::Success {
+        let artifact_kind = match file_type {
+            llvm::FileType::ObjectFile => "object_file",
+            llvm::FileType::AssemblyFile => "assembly_file",
+        };
+        record_artifact_size(self_profiler_ref, artifact_kind, output);
+        if let Some(dwo_file) = dwo_output {
+            record_artifact_size(self_profiler_ref, "dwo_file", dwo_file);
         }
-
-        result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
     }
+
+    result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
 }
 
 pub(crate) fn create_informational_target_machine(
@@ -325,13 +328,17 @@ pub(crate) fn save_temp_bitcode(
     if !cgcx.save_temps {
         return;
     }
+    let ext = format!("{name}.bc");
+    let cgu = Some(&module.name[..]);
+    let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
+    write_bitcode_to_file(module, &path)
+}
+
+fn write_bitcode_to_file(module: &ModuleCodegen<ModuleLlvm>, path: &Path) {
     unsafe {
-        let ext = format!("{name}.bc");
-        let cgu = Some(&module.name[..]);
-        let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
-        let cstr = path_to_c_string(&path);
+        let path = path_to_c_string(&path);
         let llmod = module.module_llvm.llmod();
-        llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
+        llvm::LLVMWriteBitcodeToFile(llmod, path.as_ptr());
     }
 }
 
@@ -676,7 +683,6 @@ pub(crate) unsafe fn optimize(
 ) -> Result<(), FatalError> {
     let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name);
 
-    let llmod = module.module_llvm.llmod();
     let llcx = &*module.module_llvm.llcx;
     let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt);
 
@@ -685,8 +691,7 @@ pub(crate) unsafe fn optimize(
 
     if config.emit_no_opt_bc {
         let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
-        let out = path_to_c_string(&out);
-        unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) };
+        write_bitcode_to_file(module, &out)
     }
 
     // FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts
@@ -755,31 +760,6 @@ pub(crate) unsafe fn codegen(
             create_msvc_imps(cgcx, llcx, llmod);
         }
 
-        // A codegen-specific pass manager is used to generate object
-        // files for an LLVM module.
-        //
-        // Apparently each of these pass managers is a one-shot kind of
-        // thing, so we create a new one for each type of output. The
-        // pass manager passed to the closure should be ensured to not
-        // escape the closure itself, and the manager should only be
-        // used once.
-        unsafe fn with_codegen<'ll, F, R>(
-            tm: &'ll llvm::TargetMachine,
-            llmod: &'ll llvm::Module,
-            no_builtins: bool,
-            f: F,
-        ) -> R
-        where
-            F: FnOnce(&'ll mut PassManager<'ll>) -> R,
-        {
-            unsafe {
-                let cpm = llvm::LLVMCreatePassManager();
-                llvm::LLVMAddAnalysisPasses(tm, cpm);
-                llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
-                f(cpm)
-            }
-        }
-
         // Note that if object files are just LLVM bitcode we write bitcode,
         // copy it to the .o file, and delete the bitcode if it wasn't
         // otherwise requested.
@@ -898,21 +878,17 @@ pub(crate) unsafe fn codegen(
             } else {
                 llmod
             };
-            unsafe {
-                with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                    write_output_file(
-                        dcx,
-                        tm,
-                        cpm,
-                        llmod,
-                        &path,
-                        None,
-                        llvm::FileType::AssemblyFile,
-                        &cgcx.prof,
-                        config.verify_llvm_ir,
-                    )
-                })?;
-            }
+            write_output_file(
+                dcx,
+                tm,
+                config.no_builtins,
+                llmod,
+                &path,
+                None,
+                llvm::FileType::AssemblyFile,
+                &cgcx.prof,
+                config.verify_llvm_ir,
+            )?;
         }
 
         match config.emit_obj {
@@ -936,21 +912,17 @@ pub(crate) unsafe fn codegen(
                     (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
                 };
 
-                unsafe {
-                    with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                        write_output_file(
-                            dcx,
-                            tm,
-                            cpm,
-                            llmod,
-                            &obj_out,
-                            dwo_out,
-                            llvm::FileType::ObjectFile,
-                            &cgcx.prof,
-                            config.verify_llvm_ir,
-                        )
-                    })?;
-                }
+                write_output_file(
+                    dcx,
+                    tm,
+                    config.no_builtins,
+                    llmod,
+                    &obj_out,
+                    dwo_out,
+                    llvm::FileType::ObjectFile,
+                    &cgcx.prof,
+                    config.verify_llvm_ir,
+                )?;
             }
 
             EmitObj::Bitcode => {
@@ -1077,24 +1049,18 @@ unsafe fn embed_bitcode(
         {
             // We don't need custom section flags, create LLVM globals.
             let llconst = common::bytes_in_context(llcx, bitcode);
-            let llglobal = llvm::LLVMAddGlobal(
-                llmod,
-                common::val_ty(llconst),
-                c"rustc.embedded.module".as_ptr(),
-            );
-            llvm::LLVMSetInitializer(llglobal, llconst);
+            let llglobal =
+                llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
+            llvm::set_initializer(llglobal, llconst);
 
             llvm::set_section(llglobal, bitcode_section_name(cgcx));
             llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
             llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
 
             let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
-            let llglobal = llvm::LLVMAddGlobal(
-                llmod,
-                common::val_ty(llconst),
-                c"rustc.embedded.cmdline".as_ptr(),
-            );
-            llvm::LLVMSetInitializer(llglobal, llconst);
+            let llglobal =
+                llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
+            llvm::set_initializer(llglobal, llconst);
             let section = if cgcx.target_is_like_osx {
                 c"__LLVM,__cmdline"
             } else if cgcx.target_is_like_aix {
@@ -1134,31 +1100,29 @@ fn create_msvc_imps(
     // underscores added in front).
     let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" };
 
-    unsafe {
-        let ptr_ty = Type::ptr_llcx(llcx);
-        let globals = base::iter_globals(llmod)
-            .filter(|&val| {
-                llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage
-                    && llvm::LLVMIsDeclaration(val) == 0
-            })
-            .filter_map(|val| {
-                // Exclude some symbols that we know are not Rust symbols.
-                let name = llvm::get_value_name(val);
-                if ignored(name) { None } else { Some((val, name)) }
-            })
-            .map(move |(val, name)| {
-                let mut imp_name = prefix.as_bytes().to_vec();
-                imp_name.extend(name);
-                let imp_name = CString::new(imp_name).unwrap();
-                (imp_name, val)
-            })
-            .collect::<Vec<_>>();
+    let ptr_ty = Type::ptr_llcx(llcx);
+    let globals = base::iter_globals(llmod)
+        .filter(|&val| {
+            llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage && !llvm::is_declaration(val)
+        })
+        .filter_map(|val| {
+            // Exclude some symbols that we know are not Rust symbols.
+            let name = llvm::get_value_name(val);
+            if ignored(name) { None } else { Some((val, name)) }
+        })
+        .map(move |(val, name)| {
+            let mut imp_name = prefix.as_bytes().to_vec();
+            imp_name.extend(name);
+            let imp_name = CString::new(imp_name).unwrap();
+            (imp_name, val)
+        })
+        .collect::<Vec<_>>();
 
-        for (imp_name, val) in globals {
-            let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr());
-            llvm::LLVMSetInitializer(imp, val);
-            llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage);
-        }
+    for (imp_name, val) in globals {
+        let imp = llvm::add_global(llmod, ptr_ty, &imp_name);
+
+        llvm::set_initializer(imp, val);
+        llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage);
     }
 
     // Use this function to exclude certain symbols from `__imp` generation.
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 8c94a46ebf3..78b3a7f8541 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -219,8 +219,8 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
                     bug!("symbol `{}` is already defined", sym);
                 });
+                llvm::set_initializer(g, sc);
                 unsafe {
-                    llvm::LLVMSetInitializer(g, sc);
                     llvm::LLVMSetGlobalConstant(g, True);
                     llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
                 }
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index c6855dd42e5..4a5491ec7a1 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -191,7 +191,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
             })
         });
         llvm::set_linkage(g2, llvm::Linkage::InternalLinkage);
-        unsafe { llvm::LLVMSetInitializer(g2, g1) };
+        llvm::set_initializer(g2, g1);
         g2
     } else if cx.tcx.sess.target.arch == "x86"
         && common::is_mingw_gnu_toolchain(&cx.tcx.sess.target)
@@ -235,7 +235,7 @@ impl<'ll> CodegenCx<'ll, '_> {
             }
             _ => self.define_private_global(self.val_ty(cv)),
         };
-        unsafe { llvm::LLVMSetInitializer(gv, cv) };
+        llvm::set_initializer(gv, cv);
         set_global_alignment(self, gv, align);
         llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
         gv
@@ -458,7 +458,7 @@ impl<'ll> CodegenCx<'ll, '_> {
                 new_g
             };
             set_global_alignment(self, g, alloc.align);
-            llvm::LLVMSetInitializer(g, v);
+            llvm::set_initializer(g, v);
 
             if self.should_assume_dso_local(g, true) {
                 llvm::LLVMRustSetDSOLocal(g, true);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index ba4fd75fb94..7fe527a4c07 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -616,12 +616,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
         let array = self.const_array(self.type_ptr(), values);
 
-        unsafe {
-            let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
-            llvm::LLVMSetInitializer(g, array);
-            llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
-            llvm::set_section(g, c"llvm.metadata");
-        }
+        let g = llvm::add_global(self.llmod, self.val_ty(array), name);
+        llvm::set_initializer(g, array);
+        llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
+        llvm::set_section(g, c"llvm.metadata");
     }
 }
 impl<'ll> SimpleCx<'ll> {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 2c9f1cda13a..54c5d445f66 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -73,7 +73,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
                 .define_global(section_var_name, llvm_type)
                 .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
             llvm::set_section(section_var, c".debug_gdb_scripts");
-            llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
+            llvm::set_initializer(section_var, cx.const_bytes(section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
             llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index bdc83267cca..cebceef1b93 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -235,7 +235,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     /// name.
     pub(crate) fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
         self.get_declared_value(name).and_then(|val| {
-            let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 };
+            let declaration = llvm::is_declaration(val);
             if !declaration { Some(val) } else { None }
         })
     }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 3200c94d977..8b976885904 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -824,7 +824,7 @@ fn codegen_msvc_try<'ll>(
         if bx.cx.tcx.sess.target.supports_comdat() {
             llvm::SetUniqueComdat(bx.llmod, tydesc);
         }
-        unsafe { llvm::LLVMSetInitializer(tydesc, type_info) };
+        llvm::set_initializer(tydesc, type_info);
 
         // The flag value of 8 indicates that we are catching the exception by
         // reference instead of by value. We can't use catch by value because
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 4d6a76b23ea..441d144ce50 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2359,7 +2359,7 @@ unsafe extern "C" {
     );
     pub fn LLVMRustWriteOutputFile<'a>(
         T: &'a TargetMachine,
-        PM: &PassManager<'a>,
+        PM: *mut PassManager<'a>,
         M: &'a Module,
         Output: *const c_char,
         DwoOutput: *const c_char,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index 707aeba22cc..7becba4ccd4 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -241,6 +241,10 @@ pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
     }
 }
 
+pub fn is_declaration(llglobal: &Value) -> bool {
+    unsafe { LLVMIsDeclaration(llglobal) == ffi::True }
+}
+
 pub fn get_visibility(llglobal: &Value) -> Visibility {
     unsafe { LLVMGetVisibility(llglobal) }.to_rust()
 }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index ffddf6f73aa..697852c5ed3 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2154,11 +2154,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
             }
             // FIXME(const_generics): create real const to allow fn items as const paths
-            Res::Def(DefKind::Fn | DefKind::AssocFn, _) => ty::Const::new_error_with_message(
-                tcx,
-                span,
-                "fn items cannot be used as const args",
-            ),
+            Res::Def(DefKind::Fn | DefKind::AssocFn, did) => {
+                self.dcx().span_delayed_bug(span, "function items cannot be used as const args");
+                let args = self.lower_generic_args_of_path_segment(
+                    span,
+                    did,
+                    path.segments.last().unwrap(),
+                );
+                ty::Const::new_value(tcx, ty::ValTree::zst(), Ty::new_fn_def(tcx, did, args))
+            }
 
             // Exhaustive match to be clear about what exactly we're considering to be
             // an invalid Res for a const path.
@@ -2557,27 +2561,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // reject function types that violate cmse ABI requirements
         cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);
 
-        // Find any late-bound regions declared in return type that do
-        // not appear in the arguments. These are not well-formed.
-        //
-        // Example:
-        //     for<'a> fn() -> &'a str <-- 'a is bad
-        //     for<'a> fn(&'a String) -> &'a str <-- 'a is ok
-        let inputs = bare_fn_ty.inputs();
-        let late_bound_in_args =
-            tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned()));
-        let output = bare_fn_ty.output();
-        let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output);
-
-        self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
-            struct_span_code_err!(
-                self.dcx(),
-                decl.output.span(),
-                E0581,
-                "return type references {}, which is not constrained by the fn input types",
-                br_name
-            )
-        });
+        if !bare_fn_ty.references_error() {
+            // Find any late-bound regions declared in return type that do
+            // not appear in the arguments. These are not well-formed.
+            //
+            // Example:
+            //     for<'a> fn() -> &'a str <-- 'a is bad
+            //     for<'a> fn(&'a String) -> &'a str <-- 'a is ok
+            let inputs = bare_fn_ty.inputs();
+            let late_bound_in_args =
+                tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned()));
+            let output = bare_fn_ty.output();
+            let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output);
+
+            self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
+                struct_span_code_err!(
+                    self.dcx(),
+                    decl.output.span(),
+                    E0581,
+                    "return type references {}, which is not constrained by the fn input types",
+                    br_name
+                )
+            });
+        }
 
         bare_fn_ty
     }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 55c6a122d35..480d97e377a 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -390,9 +390,6 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
 
 lint_improper_ctypes_opaque = opaque types have no C equivalent
 
-lint_improper_ctypes_pat_help = consider using the base type instead
-
-lint_improper_ctypes_pat_reason = pattern types have no C equivalent
 lint_improper_ctypes_slice_help = consider using a raw pointer instead
 
 lint_improper_ctypes_slice_reason = slices have no C equivalent
diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs
index 45b188205d2..636779fe9b4 100644
--- a/compiler/rustc_lint/src/foreign_modules.rs
+++ b/compiler/rustc_lint/src/foreign_modules.rs
@@ -241,10 +241,7 @@ fn structurally_same_type_impl<'tcx>(
             if let ty::Adt(def, args) = *ty.kind() {
                 let is_transparent = def.repr().transparent();
                 let is_non_null = types::nonnull_optimization_guaranteed(tcx, def);
-                debug!(
-                    "non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
-                    ty, is_transparent, is_non_null
-                );
+                debug!(?ty, is_transparent, is_non_null);
                 if is_transparent && !is_non_null {
                     debug_assert_eq!(def.variants().len(), 1);
                     let v = &def.variant(FIRST_VARIANT);
@@ -378,14 +375,14 @@ fn structurally_same_type_impl<'tcx>(
 
                 // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
                 // enum layout optimisation is being applied.
-                (Adt(..), _) if is_primitive_or_pointer(b) => {
+                (Adt(..) | Pat(..), _) if is_primitive_or_pointer(b) => {
                     if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) {
                         a_inner == b
                     } else {
                         false
                     }
                 }
-                (_, Adt(..)) if is_primitive_or_pointer(a) => {
+                (_, Adt(..) | Pat(..)) if is_primitive_or_pointer(a) => {
                     if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) {
                         b_inner == a
                     } else {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index d89e615e14a..c8de5e87753 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -33,6 +33,7 @@
 #![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
+#![feature(try_blocks)]
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 601d2fbfb67..68b1f435a4c 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -877,6 +877,37 @@ fn ty_is_known_nonnull<'tcx>(
                 .filter_map(|variant| transparent_newtype_field(tcx, variant))
                 .any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode))
         }
+        ty::Pat(base, pat) => {
+            ty_is_known_nonnull(tcx, typing_env, *base, mode)
+                || Option::unwrap_or_default(
+                    try {
+                        match **pat {
+                            ty::PatternKind::Range { start, end, include_end } => {
+                                match (start, end) {
+                                    (Some(start), None) => {
+                                        start.try_to_value()?.try_to_bits(tcx, typing_env)? > 0
+                                    }
+                                    (Some(start), Some(end)) => {
+                                        let start =
+                                            start.try_to_value()?.try_to_bits(tcx, typing_env)?;
+                                        let end =
+                                            end.try_to_value()?.try_to_bits(tcx, typing_env)?;
+
+                                        if include_end {
+                                            // This also works for negative numbers, as we just need
+                                            // to ensure we aren't wrapping over zero.
+                                            start > 0 && end >= start
+                                        } else {
+                                            start > 0 && end > start
+                                        }
+                                    }
+                                    _ => false,
+                                }
+                            }
+                        }
+                    },
+                )
+        }
         _ => false,
     }
 }
@@ -907,9 +938,8 @@ fn get_nullable_type<'tcx>(
             };
             return get_nullable_type(tcx, typing_env, inner_field_ty);
         }
-        ty::Int(ty) => Ty::new_int(tcx, ty),
-        ty::Uint(ty) => Ty::new_uint(tcx, ty),
-        ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
+        ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base),
+        ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty,
         // As these types are always non-null, the nullable equivalent of
         // `Option<T>` of these types are their raw pointer counterparts.
         ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
@@ -965,63 +995,69 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
     ckind: CItemKind,
 ) -> Option<Ty<'tcx>> {
     debug!("is_repr_nullable_ptr(tcx, ty = {:?})", ty);
-    if let ty::Adt(ty_def, args) = ty.kind() {
-        let field_ty = match &ty_def.variants().raw[..] {
-            [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
-                ([], [field]) | ([field], []) => field.ty(tcx, args),
-                ([field1], [field2]) => {
-                    let ty1 = field1.ty(tcx, args);
-                    let ty2 = field2.ty(tcx, args);
-
-                    if is_niche_optimization_candidate(tcx, typing_env, ty1) {
-                        ty2
-                    } else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
-                        ty1
-                    } else {
-                        return None;
+    match ty.kind() {
+        ty::Adt(ty_def, args) => {
+            let field_ty = match &ty_def.variants().raw[..] {
+                [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
+                    ([], [field]) | ([field], []) => field.ty(tcx, args),
+                    ([field1], [field2]) => {
+                        let ty1 = field1.ty(tcx, args);
+                        let ty2 = field2.ty(tcx, args);
+
+                        if is_niche_optimization_candidate(tcx, typing_env, ty1) {
+                            ty2
+                        } else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
+                            ty1
+                        } else {
+                            return None;
+                        }
                     }
-                }
+                    _ => return None,
+                },
                 _ => return None,
-            },
-            _ => return None,
-        };
+            };
 
-        if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
-            return None;
-        }
+            if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
+                return None;
+            }
 
-        // At this point, the field's type is known to be nonnull and the parent enum is Option-like.
-        // If the computed size for the field and the enum are different, the nonnull optimization isn't
-        // being applied (and we've got a problem somewhere).
-        let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
-        if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
-            bug!("improper_ctypes: Option nonnull optimization not applied?");
-        }
+            // At this point, the field's type is known to be nonnull and the parent enum is Option-like.
+            // If the computed size for the field and the enum are different, the nonnull optimization isn't
+            // being applied (and we've got a problem somewhere).
+            let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
+            if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
+                bug!("improper_ctypes: Option nonnull optimization not applied?");
+            }
 
-        // Return the nullable type this Option-like enum can be safely represented with.
-        let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
-        if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
-            bug!("should be able to compute the layout of non-polymorphic type");
-        }
+            // Return the nullable type this Option-like enum can be safely represented with.
+            let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
+            if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
+                bug!("should be able to compute the layout of non-polymorphic type");
+            }
 
-        let field_ty_abi = &field_ty_layout.ok()?.backend_repr;
-        if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi {
-            match field_ty_scalar.valid_range(&tcx) {
-                WrappingRange { start: 0, end }
-                    if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
-                {
-                    return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
-                }
-                WrappingRange { start: 1, .. } => {
-                    return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
-                }
-                WrappingRange { start, end } => {
-                    unreachable!("Unhandled start and end range: ({}, {})", start, end)
-                }
-            };
+            let field_ty_abi = &field_ty_layout.ok()?.backend_repr;
+            if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi {
+                match field_ty_scalar.valid_range(&tcx) {
+                    WrappingRange { start: 0, end }
+                        if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
+                    {
+                        return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
+                    }
+                    WrappingRange { start: 1, .. } => {
+                        return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
+                    }
+                    WrappingRange { start, end } => {
+                        unreachable!("Unhandled start and end range: ({}, {})", start, end)
+                    }
+                };
+            }
+            None
         }
+        ty::Pat(base, pat) => match **pat {
+            ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, *base),
+        },
+        _ => None,
     }
-    None
 }
 
 impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
@@ -1256,11 +1292,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                 help: Some(fluent::lint_improper_ctypes_char_help),
             },
 
-            ty::Pat(..) => FfiUnsafe {
-                ty,
-                reason: fluent::lint_improper_ctypes_pat_reason,
-                help: Some(fluent::lint_improper_ctypes_pat_help),
-            },
+            // It's just extra invariants on the type that you need to uphold,
+            // but only the base type is relevant for being representable in FFI.
+            ty::Pat(base, ..) => self.check_type_for_ffi(acc, base),
 
             ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
                 FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 343aabd7bbb..2c1adc2bcad 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1800,7 +1800,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         }
 
         let u8_type = self.tcx().types.u8;
-        match (cv.valtree, cv.ty.kind()) {
+        match (cv.valtree, *cv.ty.kind()) {
             (ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
                 ty::Slice(t) if *t == u8_type => {
                     let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
@@ -1820,13 +1820,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     return Ok(());
                 }
                 _ => {
-                    let cv = ty::Value { valtree: cv.valtree, ty: *inner_ty };
+                    let cv = ty::Value { valtree: cv.valtree, ty: inner_ty };
                     p!("&");
                     p!(pretty_print_const_valtree(cv, print_ty));
                     return Ok(());
                 }
             },
-            (ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
+            (ty::ValTree::Branch(_), ty::Array(t, _)) if t == u8_type => {
                 let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
                     bug!("expected to convert valtree to raw bytes for type {:?}", t)
                 });
@@ -1893,11 +1893,16 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
             (ty::ValTree::Leaf(leaf), ty::Ref(_, inner_ty, _)) => {
                 p!(write("&"));
-                return self.pretty_print_const_scalar_int(leaf, *inner_ty, print_ty);
+                return self.pretty_print_const_scalar_int(leaf, inner_ty, print_ty);
             }
             (ty::ValTree::Leaf(leaf), _) => {
                 return self.pretty_print_const_scalar_int(leaf, cv.ty, print_ty);
             }
+            (_, ty::FnDef(def_id, args)) => {
+                // Never allowed today, but we still encounter them in invalid const args.
+                p!(print_value_path(def_id, args));
+                return Ok(());
+            }
             // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
             // their fields instead of just dumping the memory.
             _ => {}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 508bd831ccb..03aeb8720ca 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -923,6 +923,21 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
         self.diag_metadata.current_trait_object = prev;
         self.diag_metadata.current_type_path = prev_ty;
     }
+
+    fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
+        match &t.kind {
+            TyPatKind::Range(start, end, _) => {
+                if let Some(start) = start {
+                    self.resolve_anon_const(start, AnonConstKind::ConstArg(IsRepeatExpr::No));
+                }
+                if let Some(end) = end {
+                    self.resolve_anon_const(end, AnonConstKind::ConstArg(IsRepeatExpr::No));
+                }
+            }
+            TyPatKind::Err(_) => {}
+        }
+    }
+
     fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
         let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
         self.with_generic_param_rib(
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index dcf9b6b4460..1b8f4c1be2d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
     base.max_atomic_width = Some(64);
 
     // https://developer.android.com/ndk/guides/abis.html#x86
-    base.cpu = "pentiumpro".into();
+    base.cpu = "pentium4".into();
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
     base.stack_probes = StackProbeType::Inline;
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 99b70c87ccd..9e7e96dddd7 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -18,6 +18,8 @@ use rustc_middle::ty::{
     TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
 };
 use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym};
+use rustc_type_ir::inherent::*;
+use rustc_type_ir::visit::TypeVisitableExt;
 use tracing::{debug, instrument, warn};
 
 use super::nice_region_error::placeholder_error::Highlighted;
@@ -155,27 +157,92 @@ impl UnderspecifiedArgKind {
     }
 }
 
-struct ClosureEraser<'tcx> {
-    tcx: TyCtxt<'tcx>,
+struct ClosureEraser<'a, 'tcx> {
+    infcx: &'a InferCtxt<'tcx>,
 }
 
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> {
+impl<'a, 'tcx> ClosureEraser<'a, 'tcx> {
+    fn new_infer(&mut self) -> Ty<'tcx> {
+        self.infcx.next_ty_var(DUMMY_SP)
+    }
+}
+
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
     fn cx(&self) -> TyCtxt<'tcx> {
-        self.tcx
+        self.infcx.tcx
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match ty.kind() {
             ty::Closure(_, args) => {
+                // For a closure type, we turn it into a function pointer so that it gets rendered
+                // as `fn(args) -> Ret`.
                 let closure_sig = args.as_closure().sig();
                 Ty::new_fn_ptr(
-                    self.tcx,
-                    self.tcx.signature_unclosure(closure_sig, hir::Safety::Safe),
+                    self.cx(),
+                    self.cx().signature_unclosure(closure_sig, hir::Safety::Safe),
                 )
             }
-            _ => ty.super_fold_with(self),
+            ty::Adt(_, args) if !args.iter().any(|a| a.has_infer()) => {
+                // We have a type that doesn't have any inference variables, so we replace
+                // the whole thing with `_`. The type system already knows about this type in
+                // its entirety and it is redundant to specify it for the user. The user only
+                // needs to specify the type parameters that we *couldn't* figure out.
+                self.new_infer()
+            }
+            ty::Adt(def, args) => {
+                let generics = self.cx().generics_of(def.did());
+                let generics: Vec<bool> = generics
+                    .own_params
+                    .iter()
+                    .map(|param| param.default_value(self.cx()).is_some())
+                    .collect();
+                let ty = Ty::new_adt(
+                    self.cx(),
+                    *def,
+                    self.cx().mk_args_from_iter(generics.into_iter().zip(args.iter()).map(
+                        |(has_default, arg)| {
+                            if arg.has_infer() {
+                                // This param has an unsubstituted type variable, meaning that this
+                                // type has a (potentially deeply nested) type parameter from the
+                                // corresponding type's definition. We have explicitly asked this
+                                // type to not be hidden. In either case, we keep the type and don't
+                                // substitute with `_` just yet.
+                                arg.fold_with(self)
+                            } else if has_default {
+                                // We have a type param that has a default type, like the allocator
+                                // in Vec. We decided to show `Vec` itself, because it hasn't yet
+                                // been replaced by an `_` `Infer`, but we want to ensure that the
+                                // type parameter with default types does *not* get replaced with
+                                // `_` because then we'd end up with `Vec<_, _>`, instead of
+                                // `Vec<_>`.
+                                arg
+                            } else if let GenericArgKind::Type(_) = arg.kind() {
+                                // We don't replace lifetime or const params, only type params.
+                                self.new_infer().into()
+                            } else {
+                                arg.fold_with(self)
+                            }
+                        },
+                    )),
+                );
+                ty
+            }
+            _ if ty.has_infer() => {
+                // This type has a (potentially nested) type parameter that we couldn't figure out.
+                // We will print this depth of type, so at least the type name and at least one of
+                // its type parameters.
+                ty.super_fold_with(self)
+            }
+            // We don't have an unknown type parameter anywhere, replace with `_`.
+            _ => self.new_infer(),
         }
     }
+
+    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+        // Avoid accidentally erasing the type of the const.
+        c
+    }
 }
 
 fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
@@ -219,9 +286,9 @@ fn ty_to_string<'tcx>(
 ) -> String {
     let mut printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
-    // We use `fn` ptr syntax for closures, but this only works when the closure
-    // does not capture anything.
-    let ty = ty.fold_with(&mut ClosureEraser { tcx: infcx.tcx });
+    // We use `fn` ptr syntax for closures, but this only works when the closure does not capture
+    // anything. We also remove all type parameters that are fully known to the type system.
+    let ty = ty.fold_with(&mut ClosureEraser { infcx });
 
     match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index e5c1a64c12e..520b9941ae4 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -646,7 +646,7 @@ pub const fn must_use<T>(value: T) -> T {
 /// ```
 ///
 ///
-#[unstable(feature = "likely_unlikely", issue = "26179")]
+#[unstable(feature = "likely_unlikely", issue = "136873")]
 #[inline(always)]
 pub const fn likely(b: bool) -> bool {
     crate::intrinsics::likely(b)
@@ -696,7 +696,7 @@ pub const fn likely(b: bool) -> bool {
 ///     }
 /// }
 /// ```
-#[unstable(feature = "likely_unlikely", issue = "26179")]
+#[unstable(feature = "likely_unlikely", issue = "136873")]
 #[inline(always)]
 pub const fn unlikely(b: bool) -> bool {
     crate::intrinsics::unlikely(b)
@@ -729,7 +729,7 @@ pub const fn unlikely(b: bool) -> bool {
 ///     }
 /// }
 /// ```
-#[unstable(feature = "cold_path", issue = "26179")]
+#[unstable(feature = "cold_path", issue = "136873")]
 #[inline(always)]
 pub const fn cold_path() {
     crate::intrinsics::cold_path()
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 05555f537c9..a086498fcbd 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -165,7 +165,7 @@ target | std | notes
 `i586-pc-windows-msvc` | * | 32-bit Windows (original Pentium) [^x86_32-floats-x87]
 `i586-unknown-linux-gnu` | ✓ | 32-bit Linux (kernel 3.2, glibc 2.17, original Pentium) [^x86_32-floats-x87]
 `i586-unknown-linux-musl` | ✓ | 32-bit Linux (musl 1.2.3, original Pentium) [^x86_32-floats-x87]
-[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android ([PentiumPro with SSE](https://developer.android.com/ndk/guides/abis.html#x86)) [^x86_32-floats-return-ABI]
+[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android ([Pentium 4 plus various extensions](https://developer.android.com/ndk/guides/abis.html#x86)) [^x86_32-floats-return-ABI]
 [`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 32-bit x86 MinGW (Windows 10+, Pentium 4), LLVM ABI [^x86_32-floats-return-ABI]
 [`i686-unknown-freebsd`](platform-support/freebsd.md) | ✓ | 32-bit x86 FreeBSD (Pentium 4) [^x86_32-floats-return-ABI]
 `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 (Pentium 4) [^x86_32-floats-return-ABI]
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index 1d88726d945..bafed41e39f 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -75,12 +75,12 @@ fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool
     }
 }
 
-pub(crate) struct RangeOperand<'a> {
-    operand: &'a Option<ptr::P<ast::Expr>>,
-    pub(crate) span: Span,
+pub(crate) struct RangeOperand<'a, T> {
+    pub operand: &'a Option<ptr::P<T>>,
+    pub span: Span,
 }
 
-impl<'a> Rewrite for RangeOperand<'a> {
+impl<'a, T: Rewrite> Rewrite for RangeOperand<'a, T> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         self.rewrite_result(context, shape).ok()
     }
@@ -259,40 +259,7 @@ impl Rewrite for Pat {
             }
             PatKind::Never => Err(RewriteError::Unknown),
             PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
-                let infix = match end_kind.node {
-                    RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
-                    RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
-                    RangeEnd::Excluded => "..",
-                };
-                let infix = if context.config.spaces_around_ranges() {
-                    let lhs_spacing = match lhs {
-                        None => "",
-                        Some(_) => " ",
-                    };
-                    let rhs_spacing = match rhs {
-                        None => "",
-                        Some(_) => " ",
-                    };
-                    format!("{lhs_spacing}{infix}{rhs_spacing}")
-                } else {
-                    infix.to_owned()
-                };
-                let lspan = self.span.with_hi(end_kind.span.lo());
-                let rspan = self.span.with_lo(end_kind.span.hi());
-                rewrite_pair(
-                    &RangeOperand {
-                        operand: lhs,
-                        span: lspan,
-                    },
-                    &RangeOperand {
-                        operand: rhs,
-                        span: rspan,
-                    },
-                    PairParts::infix(&infix),
-                    context,
-                    shape,
-                    SeparatorPlace::Front,
-                )
+                rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span)
             }
             PatKind::Ref(ref pat, mutability) => {
                 let prefix = format!("&{}", format_mutability(mutability));
@@ -359,6 +326,50 @@ impl Rewrite for Pat {
     }
 }
 
+pub fn rewrite_range_pat<T: Rewrite>(
+    context: &RewriteContext<'_>,
+    shape: Shape,
+    lhs: &Option<ptr::P<T>>,
+    rhs: &Option<ptr::P<T>>,
+    end_kind: &rustc_span::source_map::Spanned<RangeEnd>,
+    span: Span,
+) -> RewriteResult {
+    let infix = match end_kind.node {
+        RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
+        RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
+        RangeEnd::Excluded => "..",
+    };
+    let infix = if context.config.spaces_around_ranges() {
+        let lhs_spacing = match lhs {
+            None => "",
+            Some(_) => " ",
+        };
+        let rhs_spacing = match rhs {
+            None => "",
+            Some(_) => " ",
+        };
+        format!("{lhs_spacing}{infix}{rhs_spacing}")
+    } else {
+        infix.to_owned()
+    };
+    let lspan = span.with_hi(end_kind.span.lo());
+    let rspan = span.with_lo(end_kind.span.hi());
+    rewrite_pair(
+        &RangeOperand {
+            operand: lhs,
+            span: lspan,
+        },
+        &RangeOperand {
+            operand: rhs,
+            span: rspan,
+        },
+        PairParts::infix(&infix),
+        context,
+        shape,
+        SeparatorPlace::Front,
+    )
+}
+
 fn rewrite_struct_pat(
     qself: &Option<ptr::P<ast::QSelf>>,
     path: &ast::Path,
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs
index 6b3e40b9115..e93eb53cd87 100644
--- a/src/tools/rustfmt/src/spanned.rs
+++ b/src/tools/rustfmt/src/spanned.rs
@@ -211,7 +211,7 @@ impl Spanned for ast::PreciseCapturingArg {
     }
 }
 
-impl<'a> Spanned for RangeOperand<'a> {
+impl<'a, T> Spanned for RangeOperand<'a, T> {
     fn span(&self) -> Span {
         self.span
     }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index f8b713117f4..0009490e86f 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -18,6 +18,7 @@ use crate::lists::{
 use crate::macros::{MacroPosition, rewrite_macro};
 use crate::overflow;
 use crate::pairs::{PairParts, rewrite_pair};
+use crate::patterns::rewrite_range_pat;
 use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
@@ -1045,6 +1046,21 @@ impl Rewrite for ast::Ty {
     }
 }
 
+impl Rewrite for ast::TyPat {
+    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        match self.kind {
+            ast::TyPatKind::Range(ref lhs, ref rhs, ref end_kind) => {
+                rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span)
+            }
+            ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
+        }
+    }
+}
+
 fn rewrite_bare_fn(
     bare_fn: &ast::BareFnTy,
     span: Span,
diff --git a/tests/ui/async-await/unconstrained-lifetimes.rs b/tests/ui/async-await/unconstrained-lifetimes.rs
new file mode 100644
index 00000000000..50ab7bae73d
--- /dev/null
+++ b/tests/ui/async-await/unconstrained-lifetimes.rs
@@ -0,0 +1,9 @@
+//@ edition: 2021
+
+// Make sure we don't complain about the implicit `-> impl Future` capturing an
+// unconstrained anonymous lifetime.
+
+async fn foo(_: Missing<'_>) {}
+//~^ ERROR cannot find type `Missing` in this scope
+
+fn main() {}
diff --git a/tests/ui/async-await/unconstrained-lifetimes.stderr b/tests/ui/async-await/unconstrained-lifetimes.stderr
new file mode 100644
index 00000000000..18a46a3b555
--- /dev/null
+++ b/tests/ui/async-await/unconstrained-lifetimes.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/unconstrained-lifetimes.rs:6:17
+   |
+LL | async fn foo(_: Missing<'_>) {}
+   |                 ^^^^^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs
new file mode 100644
index 00000000000..1c3274f6a37
--- /dev/null
+++ b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs
@@ -0,0 +1,13 @@
+// Make sure we don't ICE when encountering an fn item during lowering in mGCA.
+
+#![feature(min_generic_const_args)]
+//~^ WARN the feature `min_generic_const_args` is incomplete
+
+trait A<T> {}
+
+impl A<[usize; fn_item]> for () {}
+//~^ ERROR the constant `fn_item` is not of type `usize`
+
+fn fn_item() {}
+
+fn main() {}
diff --git a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr
new file mode 100644
index 00000000000..89fc8270e3e
--- /dev/null
+++ b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr
@@ -0,0 +1,19 @@
+warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unexpected-fn-item-in-array.rs:3:12
+   |
+LL | #![feature(min_generic_const_args)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: the constant `fn_item` is not of type `usize`
+  --> $DIR/unexpected-fn-item-in-array.rs:8:6
+   |
+LL | impl A<[usize; fn_item]> for () {}
+   |      ^^^^^^^^^^^^^^^^^^^ expected `usize`, found fn item
+   |
+   = note: the length of array `[usize; fn_item]` must be type `usize`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr
index a16e832f8ef..ee17f7737cf 100644
--- a/tests/ui/inference/cannot-infer-closure-circular.stderr
+++ b/tests/ui/inference/cannot-infer-closure-circular.stderr
@@ -9,8 +9,8 @@ LL |         Ok(v)
    |
 help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified
    |
-LL |     let x = |r: Result<(), E>| {
-   |               +++++++++++++++
+LL |     let x = |r: Result<_, E>| {
+   |               ++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr
index 4e9a74c1e40..1ec8a33eb82 100644
--- a/tests/ui/inference/erase-type-params-in-label.stderr
+++ b/tests/ui/inference/erase-type-params-in-label.stderr
@@ -12,8 +12,8 @@ LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
    |                 ^^^^^^^ required by this bound in `foo`
 help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
    |
-LL |     let foo: Foo<i32, &str, W, Z> = foo(1, "");
-   |            ++++++++++++++++++++++
+LL |     let foo: Foo<_, &_, W, Z> = foo(1, "");
+   |            ++++++++++++++++++
 
 error[E0283]: type annotations needed for `Bar<i32, &str, _>`
   --> $DIR/erase-type-params-in-label.rs:5:9
@@ -29,8 +29,8 @@ LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
    |                 ^^^^^^^ required by this bound in `bar`
 help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
    |
-LL |     let bar: Bar<i32, &str, Z> = bar(1, "");
-   |            +++++++++++++++++++
+LL |     let bar: Bar<_, &_, Z> = bar(1, "");
+   |            +++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr
index 391ed16f349..27382e30134 100644
--- a/tests/ui/inference/issue-104649.stderr
+++ b/tests/ui/inference/issue-104649.stderr
@@ -6,8 +6,8 @@ LL |     let a = A(Result::Ok(Result::Ok(())));
    |
 help: consider giving `a` an explicit type, where the type for type parameter `E` is specified
    |
-LL |     let a: A<std::result::Result<std::result::Result<(), E>, Error>> = A(Result::Ok(Result::Ok(())));
-   |          +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL |     let a: A<std::result::Result<std::result::Result<_, E>, _>> = A(Result::Ok(Result::Ok(())));
+   |          ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr
index 69d1d71ef3c..97ccad9e785 100644
--- a/tests/ui/inference/issue-83606.stderr
+++ b/tests/ui/inference/issue-83606.stderr
@@ -11,8 +11,8 @@ LL | fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] {
    |        ^^^^^^^^^^^^^^ required by this const generic parameter in `foo`
 help: consider giving this pattern a type, where the value of const parameter `N` is specified
    |
-LL |     let _: [usize; N] = foo("foo");
-   |          ++++++++++++
+LL |     let _: [_; N] = foo("foo");
+   |          ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
new file mode 100644
index 00000000000..4fd15eea9e0
--- /dev/null
+++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
@@ -0,0 +1,10 @@
+type A = (i32, i32, i32, i32);
+type B = (A, A, A, A);
+type C = (B, B, B, B);
+type D = (C, C, C, C);
+
+fn foo(x: D) {
+    let y = Err(x); //~ ERROR type annotations needed for `Result<_
+}
+
+fn main() {}
diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
new file mode 100644
index 00000000000..65fe2ffcb7f
--- /dev/null
+++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `Result<_, ((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))>`
+  --> $DIR/really-long-type-in-let-binding-without-sufficient-type-info.rs:7:9
+   |
+LL |     let y = Err(x);
+   |         ^   ------ type must be known at this point
+   |
+help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
+   |
+LL |     let y: Result<T, _> = Err(x);
+   |          ++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs
index 9bbb20246df..e4477c96202 100644
--- a/tests/ui/lint/clashing-extern-fn.rs
+++ b/tests/ui/lint/clashing-extern-fn.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 //@ aux-build:external_extern_fn.rs
 #![crate_type = "lib"]
-
+#![feature(pattern_type_macro, pattern_types)]
 mod redeclared_different_signature {
     mod a {
         extern "C" {
@@ -490,3 +490,33 @@ mod hidden_niche {
         }
     }
 }
+
+mod pattern_types {
+    mod a {
+        use std::pat::pattern_type;
+        #[repr(transparent)]
+        struct NonZeroUsize(pattern_type!(usize is 1..));
+        extern "C" {
+            fn pt_non_zero_usize() -> pattern_type!(usize is 1..);
+            fn pt_non_zero_usize_opt() -> Option<pattern_type!(usize is 1..)>;
+            fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>;
+            //~^ WARN not FFI-safe
+            fn pt_non_null_ptr() -> pattern_type!(usize is 1..);
+            fn pt_non_zero_usize_wrapper() -> NonZeroUsize;
+            fn pt_non_zero_usize_wrapper_opt() -> Option<NonZeroUsize>;
+        }
+    }
+    mod b {
+        extern "C" {
+            // If there's a clash in either of these cases you're either gaining an incorrect
+            // invariant that the value is non-zero, or you're missing out on that invariant. Both
+            // cases are warning for, from both a caller-convenience and optimisation perspective.
+            fn pt_non_zero_usize() -> usize;
+            fn pt_non_zero_usize_opt() -> usize;
+            fn pt_non_null_ptr() -> *const ();
+            //~^ WARN `pt_non_null_ptr` redeclared with a different signature
+            fn pt_non_zero_usize_wrapper() -> usize;
+            fn pt_non_zero_usize_wrapper_opt() -> usize;
+        }
+    }
+}
diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr
index 48dd1adbc1f..118b18b224c 100644
--- a/tests/ui/lint/clashing-extern-fn.stderr
+++ b/tests/ui/lint/clashing-extern-fn.stderr
@@ -17,6 +17,15 @@ LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
+warning: `extern` block uses type `Option<(usize) is 0..=>`, which is not FFI-safe
+  --> $DIR/clashing-extern-fn.rs:502:54
+   |
+LL |             fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>;
+   |                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
 warning: `clash` redeclared with a different signature
   --> $DIR/clashing-extern-fn.rs:13:13
    |
@@ -258,5 +267,17 @@ LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
    = note: expected `unsafe extern "C" fn() -> usize`
               found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>`
 
-warning: 22 warnings emitted
+warning: `pt_non_null_ptr` redeclared with a different signature
+  --> $DIR/clashing-extern-fn.rs:516:13
+   |
+LL |             fn pt_non_null_ptr() -> pattern_type!(usize is 1..);
+   |             ---------------------------------------------------- `pt_non_null_ptr` previously declared here
+...
+LL |             fn pt_non_null_ptr() -> *const ();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
+   |
+   = note: expected `unsafe extern "C" fn() -> (usize) is 1..=`
+              found `unsafe extern "C" fn() -> *const ()`
+
+warning: 24 warnings emitted
 
diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs
index 19af1de9576..0d19d5b5347 100644
--- a/tests/ui/lint/lint-ctypes-enum.rs
+++ b/tests/ui/lint/lint-ctypes-enum.rs
@@ -94,6 +94,7 @@ extern "C" {
     fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
     //~^ ERROR `extern` block uses type
     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>); //~ ERROR `extern` block uses type
+    fn option_u8(x: Option<u8>); //~ ERROR `extern` block uses type
 
     fn result_ref_t(x: Result<&'static u8, ()>);
     fn result_fn_t(x: Result<extern "C" fn(), ()>);
diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr
index 8e92e7e6946..a491bd19605 100644
--- a/tests/ui/lint/lint-ctypes-enum.stderr
+++ b/tests/ui/lint/lint-ctypes-enum.stderr
@@ -79,8 +79,17 @@ LL |     fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
+error: `extern` block uses type `Option<u8>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-enum.rs:97:21
+   |
+LL |     fn option_u8(x: Option<u8>);
+   |                     ^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
+   = note: enum has no representation hint
+
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:106:33
+  --> $DIR/lint-ctypes-enum.rs:107:33
    |
 LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -88,7 +97,7 @@ LL |     fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:113:33
+  --> $DIR/lint-ctypes-enum.rs:114:33
    |
 LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -96,7 +105,7 @@ LL |     fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:118:38
+  --> $DIR/lint-ctypes-enum.rs:119:38
    |
 LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -105,7 +114,7 @@ LL |     fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:120:30
+  --> $DIR/lint-ctypes-enum.rs:121:30
    |
 LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -114,7 +123,7 @@ LL |     fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:124:51
+  --> $DIR/lint-ctypes-enum.rs:125:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -123,7 +132,7 @@ LL |     fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:126:53
+  --> $DIR/lint-ctypes-enum.rs:127:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -132,7 +141,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:128:51
+  --> $DIR/lint-ctypes-enum.rs:129:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -141,7 +150,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>,
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:131:49
+  --> $DIR/lint-ctypes-enum.rs:132:49
    |
 LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -150,7 +159,7 @@ LL |     fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Fi
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:133:30
+  --> $DIR/lint-ctypes-enum.rs:134:30
    |
 LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -159,7 +168,7 @@ LL |     fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:144:33
+  --> $DIR/lint-ctypes-enum.rs:145:33
    |
 LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -167,7 +176,7 @@ LL |     fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:151:33
+  --> $DIR/lint-ctypes-enum.rs:152:33
    |
 LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -175,7 +184,7 @@ LL |     fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:156:38
+  --> $DIR/lint-ctypes-enum.rs:157:38
    |
 LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -184,7 +193,7 @@ LL |     fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZe
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:158:30
+  --> $DIR/lint-ctypes-enum.rs:159:30
    |
 LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -193,7 +202,7 @@ LL |     fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:162:51
+  --> $DIR/lint-ctypes-enum.rs:163:51
    |
 LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -202,7 +211,7 @@ LL |     fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:164:53
+  --> $DIR/lint-ctypes-enum.rs:165:53
    |
 LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
    |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -211,7 +220,7 @@ LL |     fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:166:51
+  --> $DIR/lint-ctypes-enum.rs:167:51
    |
 LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -220,7 +229,7 @@ LL |     fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:169:49
+  --> $DIR/lint-ctypes-enum.rs:170:49
    |
 LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -229,7 +238,7 @@ LL |     fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:171:30
+  --> $DIR/lint-ctypes-enum.rs:172:30
    |
 LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -238,7 +247,7 @@ LL |     fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-enum.rs:173:27
+  --> $DIR/lint-ctypes-enum.rs:174:27
    |
 LL |     fn result_unit_t_e(x: Result<(), ()>);
    |                           ^^^^^^^^^^^^^^ not FFI-safe
@@ -246,5 +255,5 @@ LL |     fn result_unit_t_e(x: Result<(), ()>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: aborting due to 26 previous errors
+error: aborting due to 27 previous errors
 
diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr
index 3176a2d490e..9bcd07f8bf1 100644
--- a/tests/ui/type-inference/or_else-multiple-type-params.stderr
+++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr
@@ -6,8 +6,8 @@ LL |         .or_else(|err| {
    |
 help: try giving this closure an explicit return type
    |
-LL |         .or_else(|err| -> Result<Child, F> {
-   |                        +++++++++++++++++++
+LL |         .or_else(|err| -> Result<_, F> {
+   |                        +++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr
index c5d9691a029..8cff0cee7b9 100644
--- a/tests/ui/type/pattern_types/assoc_const.default.stderr
+++ b/tests/ui/type/pattern_types/assoc_const.default.stderr
@@ -1,79 +1,38 @@
-error[E0658]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:17:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:17:41
    |
 LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                         ^ cannot perform const operation using `T`
    |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error[E0658]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:17:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:17:61
    |
 LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                             ^ cannot perform const operation using `T`
    |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:17:19
-   |
-LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:17:19
-   |
-LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0658]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:22:19
-   |
-LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:22:19
-   |
-LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:22:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:20:40
    |
 LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                        ^^^^^^^^ cannot perform const operation using `T`
    |
-   = note: this may fail depending on what value the parameter takes
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:22:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:20:51
    |
 LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                   ^^^^^^ cannot perform const operation using `T`
    |
-   = note: this may fail depending on what value the parameter takes
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs
index 87886587d51..90508801990 100644
--- a/tests/ui/type/pattern_types/assoc_const.rs
+++ b/tests/ui/type/pattern_types/assoc_const.rs
@@ -15,14 +15,10 @@ trait Foo {
 }
 
 fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
-//[default]~^ ERROR: constant expression depends on a generic parameter
-//[default]~| ERROR: constant expression depends on a generic parameter
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
+//[default]~^ ERROR: generic parameters may not be used in const operations
+//[default]~| ERROR: generic parameters may not be used in const operations
 fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-//[default]~^ ERROR: constant expression depends on a generic parameter
-//[default]~| ERROR: constant expression depends on a generic parameter
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
+//[default]~^ ERROR: generic parameters may not be used in const operations
+//[default]~| ERROR: generic parameters may not be used in const operations
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs
index 0f10bf8ce62..c28fda6f91a 100644
--- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs
+++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs
@@ -5,7 +5,7 @@
 //@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
 //@ rustc-env:RUST_BACKTRACE=0
 
-#![feature(pattern_types, pattern_type_macro)]
+#![feature(pattern_types, pattern_type_macro, generic_const_exprs)]
 #![allow(internal_features)]
 
 type Pat<const START: u32, const END: u32> =
diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr
index fbe80a19863..ffc6068eb17 100644
--- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr
+++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr
@@ -1,4 +1,11 @@
-error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad_const_generics_args_on_const_param.rs:8:47
+   |
+LL | #![feature(pattern_types, pattern_type_macro, generic_const_exprs)]
+   |                                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible
   --> $DIR/bad_const_generics_args_on_const_param.rs:12:36
    |
 LL |     std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
@@ -10,5 +17,5 @@ query stack during panic:
 #0 [type_of] expanding type alias `Pat`
 #1 [check_well_formed] checking that `Pat` is well-formed
 ... and 2 other queries... use `env RUST_BACKTRACE=1` to see the full query stack
-error: aborting due to 1 previous error
+error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs
index 49c87f4fa0d..ed19b10671a 100644
--- a/tests/ui/type/pattern_types/const_block.rs
+++ b/tests/ui/type/pattern_types/const_block.rs
@@ -1,10 +1,10 @@
 #![feature(pattern_types)]
 #![feature(pattern_type_macro)]
 #![feature(inline_const_pat)]
+//@ check-pass
 
 use std::pat::pattern_type;
 
 fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-//~^ ERROR: cycle
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/const_block.stderr b/tests/ui/type/pattern_types/const_block.stderr
deleted file mode 100644
index 82b616105af..00000000000
--- a/tests/ui/type/pattern_types/const_block.stderr
+++ /dev/null
@@ -1,72 +0,0 @@
-error[E0391]: cycle detected when evaluating type-level constant
-  --> $DIR/const_block.rs:7:36
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                    ^^^^^^^^^^^^^^
-   |
-note: ...which requires const-evaluating + checking `bar::{constant#2}`...
-  --> $DIR/const_block.rs:7:36
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                    ^^^^^^^^^^^^^^
-note: ...which requires caching mir of `bar::{constant#2}` for CTFE...
-  --> $DIR/const_block.rs:7:36
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                    ^^^^^^^^^^^^^^
-note: ...which requires elaborating drops for `bar::{constant#2}`...
-  --> $DIR/const_block.rs:7:36
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                    ^^^^^^^^^^^^^^
-note: ...which requires borrow-checking `bar::{constant#2}`...
-  --> $DIR/const_block.rs:7:36
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                    ^^^^^^^^^^^^^^
-note: ...which requires borrow-checking `bar::{constant#0}`...
-  --> $DIR/const_block.rs:7:41
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                         ^^^^^^^^^
-note: ...which requires promoting constants in MIR for `bar::{constant#0}`...
-  --> $DIR/const_block.rs:7:41
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                         ^^^^^^^^^
-note: ...which requires const checking `bar::{constant#0}`...
-  --> $DIR/const_block.rs:7:41
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                         ^^^^^^^^^
-note: ...which requires building MIR for `bar::{constant#0}`...
-  --> $DIR/const_block.rs:7:41
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                         ^^^^^^^^^
-note: ...which requires match-checking `bar::{constant#0}`...
-  --> $DIR/const_block.rs:7:41
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                         ^^^^^^^^^
-note: ...which requires type-checking `bar::{constant#0}`...
-  --> $DIR/const_block.rs:7:41
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   |                                         ^^^^^^^^^
-note: ...which requires type-checking `bar`...
-  --> $DIR/const_block.rs:7:1
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires evaluating type-level constant, completing the cycle
-note: cycle used when checking that `bar` is well-formed
-  --> $DIR/const_block.rs:7:1
-   |
-LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
index b90ba478402..b4f4bd656f5 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
@@ -12,3 +12,4 @@ type Positive = pattern_type!(i32 is 0..);
 //~^ use of unstable library feature `pattern_type_macro`
 type Always = pattern_type!(Option<u32> is Some(_));
 //~^ use of unstable library feature `pattern_type_macro`
+//~| ERROR pattern not supported in pattern types
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
index 69239d68bdc..12508bcb54a 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
@@ -48,6 +48,12 @@ LL | type Always = pattern_type!(Option<u32> is Some(_));
    = help: add `#![feature(pattern_type_macro)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 5 previous errors
+error: pattern not supported in pattern types
+  --> $DIR/feature-gate-pattern_types.rs:13:44
+   |
+LL | type Always = pattern_type!(Option<u32> is Some(_));
+   |                                            ^^^^^^^
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs
index 50c355c8de6..c6b4b325fa3 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Zno-analysis
-//@ check-pass
 
 #![feature(pattern_type_macro)]
 
@@ -10,3 +9,4 @@ type Percent = pattern_type!(u32 is 0..=100);
 type Negative = pattern_type!(i32 is ..=0);
 type Positive = pattern_type!(i32 is 0..);
 type Always = pattern_type!(Option<u32> is Some(_));
+//~^ ERROR: pattern not supported in pattern types
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr
new file mode 100644
index 00000000000..81bf9dea0e2
--- /dev/null
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr
@@ -0,0 +1,8 @@
+error: pattern not supported in pattern types
+  --> $DIR/feature-gate-pattern_types2.rs:11:44
+   |
+LL | type Always = pattern_type!(Option<u32> is Some(_));
+   |                                            ^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 11066c90edb..19ae66f7a07 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -678,7 +678,7 @@ mod types {
         /*! FIXME: todo */
     }
     /// TyKind::Pat
-    fn ty_pat() { let _: u32 is 1..; }
+    fn ty_pat() { let _: u32 is const 1..; }
 }
 mod visibilities {
     /// VisibilityKind::Public