diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index b6f331d316cc9..08621c1c56a14 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3348,11 +3348,18 @@ pub struct Impl {
     pub items: ThinVec<P<AssocItem>>,
 }
 
+#[derive(Clone, Encodable, Decodable, Debug, Default)]
+pub struct FnContract {
+    pub requires: Option<P<Expr>>,
+    pub ensures: Option<P<Expr>>,
+}
+
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Fn {
     pub defaultness: Defaultness,
     pub generics: Generics,
     pub sig: FnSig,
+    pub contract: Option<P<FnContract>>,
     pub body: Option<P<Block>>,
 }
 
@@ -3650,7 +3657,7 @@ mod size_asserts {
     static_assert_size!(Block, 32);
     static_assert_size!(Expr, 72);
     static_assert_size!(ExprKind, 40);
-    static_assert_size!(Fn, 160);
+    static_assert_size!(Fn, 168);
     static_assert_size!(ForeignItem, 88);
     static_assert_size!(ForeignItemKind, 16);
     static_assert_size!(GenericArg, 24);
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 7caf7c4c35687..70616fe87691b 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -143,6 +143,10 @@ pub trait MutVisitor: Sized {
         walk_flat_map_assoc_item(self, i, ctxt)
     }
 
+    fn visit_contract(&mut self, c: &mut P<FnContract>) {
+        walk_contract(self, c);
+    }
+
     fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
         walk_fn_decl(self, d);
     }
@@ -958,13 +962,16 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
             _ctxt,
             _ident,
             _vis,
-            Fn { defaultness, generics, body, sig: FnSig { header, decl, span } },
+            Fn { defaultness, generics, contract, body, sig: FnSig { header, decl, span } },
         ) => {
             // Identifier and visibility are visited as a part of the item.
             visit_defaultness(vis, defaultness);
             vis.visit_fn_header(header);
             vis.visit_generics(generics);
             vis.visit_fn_decl(decl);
+            if let Some(contract) = contract {
+                vis.visit_contract(contract);
+            }
             if let Some(body) = body {
                 vis.visit_block(body);
             }
@@ -979,6 +986,16 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
     }
 }
 
+fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut P<FnContract>) {
+    let FnContract { requires, ensures } = contract.deref_mut();
+    if let Some(pred) = requires {
+        vis.visit_expr(pred);
+    }
+    if let Some(pred) = ensures {
+        vis.visit_expr(pred);
+    }
+}
+
 fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut P<FnDecl>) {
     let FnDecl { inputs, output } = decl.deref_mut();
     inputs.flat_map_in_place(|param| vis.flat_map_param(param));
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 232fd546de9a3..714b074f930c2 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -188,6 +188,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) -> Self::Result {
         walk_closure_binder(self, b)
     }
+    fn visit_contract(&mut self, c: &'ast FnContract) -> Self::Result {
+        walk_contract(self, c)
+    }
     fn visit_where_predicate(&mut self, p: &'ast WherePredicate) -> Self::Result {
         walk_where_predicate(self, p)
     }
@@ -800,6 +803,17 @@ pub fn walk_closure_binder<'a, V: Visitor<'a>>(
     V::Result::output()
 }
 
+pub fn walk_contract<'a, V: Visitor<'a>>(visitor: &mut V, c: &'a FnContract) -> V::Result {
+    let FnContract { requires, ensures } = c;
+    if let Some(pred) = requires {
+        visitor.visit_expr(pred);
+    }
+    if let Some(pred) = ensures {
+        visitor.visit_expr(pred);
+    }
+    V::Result::output()
+}
+
 pub fn walk_where_predicate<'a, V: Visitor<'a>>(
     visitor: &mut V,
     predicate: &'a WherePredicate,
@@ -862,12 +876,13 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
             _ctxt,
             _ident,
             _vis,
-            Fn { defaultness: _, sig: FnSig { header, decl, span: _ }, generics, body },
+            Fn { defaultness: _, sig: FnSig { header, decl, span: _ }, generics, contract, body },
         ) => {
             // Identifier and visibility are visited as a part of the item.
             try_visit!(visitor.visit_fn_header(header));
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_fn_decl(decl));
+            visit_opt!(visitor, visit_contract, contract);
             visit_opt!(visitor, visit_block, body);
         }
         FnKind::Closure(binder, coroutine_kind, decl, body) => {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 1267281f73ebe..8125da361b814 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -314,8 +314,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label))
                 }
                 ExprKind::Ret(e) => {
-                    let e = e.as_ref().map(|x| self.lower_expr(x));
-                    hir::ExprKind::Ret(e)
+                    let expr = e.as_ref().map(|x| self.lower_expr(x));
+                    self.checked_return(expr)
                 }
                 ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
                 ExprKind::Become(sub_expr) => {
@@ -382,6 +382,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
+    /// Create an `ExprKind::Ret` that is preceded by a call to check contract ensures clause.
+    fn checked_return(&mut self, opt_expr: Option<&'hir hir::Expr<'hir>>) -> hir::ExprKind<'hir> {
+        let checked_ret = if let Some(Some((span, fresh_ident))) =
+            self.contract.as_ref().map(|c| c.ensures.as_ref().map(|e| (e.expr.span, e.fresh_ident)))
+        {
+            let expr = opt_expr.unwrap_or_else(|| self.expr_unit(span));
+            Some(self.inject_ensures_check(expr, span, fresh_ident.0, fresh_ident.2))
+        } else {
+            opt_expr
+        };
+        hir::ExprKind::Ret(checked_ret)
+    }
+
+    /// Wraps an expression with a call to the ensures check before it gets returned.
+    pub(crate) fn inject_ensures_check(
+        &mut self,
+        expr: &'hir hir::Expr<'hir>,
+        span: Span,
+        check_ident: Ident,
+        check_hir_id: HirId,
+    ) -> &'hir hir::Expr<'hir> {
+        let checker_fn = self.expr_ident(span, check_ident, check_hir_id);
+        let span = self.mark_span_with_reason(DesugaringKind::Contract, span, None);
+        self.expr_call(span, checker_fn, std::slice::from_ref(expr))
+    }
+
     pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
         self.with_new_scopes(c.value.span, |this| {
             let def_id = this.local_def_id(c.id);
@@ -1970,7 +1996,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     ),
                 ))
             } else {
-                self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr))))
+                let ret_expr = self.checked_return(Some(from_residual_expr));
+                self.arena.alloc(self.expr(try_span, ret_expr))
             };
             self.lower_attrs(ret_expr.hir_id, &attrs);
 
@@ -2019,7 +2046,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let target_id = Ok(catch_id);
             hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
         } else {
-            hir::ExprKind::Ret(Some(from_yeet_expr))
+            self.checked_return(Some(from_yeet_expr))
         }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 74870d741504c..c96110fee619b 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -207,9 +207,40 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 sig: FnSig { decl, header, span: fn_sig_span },
                 generics,
                 body,
+                contract,
                 ..
             }) => {
                 self.with_new_scopes(*fn_sig_span, |this| {
+                    assert!(this.contract.is_none());
+                    if let Some(contract) = contract {
+                        let requires = contract.requires.clone();
+                        let ensures = contract.ensures.clone();
+                        let ensures = ensures.map(|ens| {
+                            // FIXME: this needs to be a fresh (or illegal) identifier to prevent
+                            // accidental capture of a parameter or global variable.
+                            let checker_ident: Ident =
+                                Ident::from_str_and_span("__ensures_checker", ens.span);
+                            let (checker_pat, checker_hir_id) = this.pat_ident_binding_mode_mut(
+                                ens.span,
+                                checker_ident,
+                                hir::BindingMode::NONE,
+                            );
+
+                            crate::FnContractLoweringEnsures {
+                                expr: ens,
+                                fresh_ident: (checker_ident, checker_pat, checker_hir_id),
+                            }
+                        });
+
+                        // Note: `with_new_scopes` will reinstall the outer
+                        // item's contract (if any) after its callback finishes.
+                        this.contract.replace(crate::FnContractLoweringInfo {
+                            span,
+                            requires,
+                            ensures,
+                        });
+                    }
+
                     // Note: we don't need to change the return type from `T` to
                     // `impl Future<Output = T>` here because lower_body
                     // only cares about the input argument patterns in the function
@@ -1054,10 +1085,64 @@ impl<'hir> LoweringContext<'_, 'hir> {
         body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
     ) -> hir::BodyId {
         self.lower_body(|this| {
-            (
-                this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x))),
-                body(this),
-            )
+            let params =
+                this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x)));
+            let result = body(this);
+
+            let opt_contract = this.contract.take();
+
+            // { body }
+            // ==>
+            // { contract_requires(PRECOND); { body } }
+            let Some(contract) = opt_contract else { return (params, result) };
+            let result_ref = this.arena.alloc(result);
+            let lit_unit = |this: &mut LoweringContext<'_, 'hir>| {
+                this.expr(contract.span, hir::ExprKind::Tup(&[]))
+            };
+
+            let precond: hir::Stmt<'hir> = if let Some(req) = contract.requires {
+                let lowered_req = this.lower_expr_mut(&req);
+                let precond = this.expr_call_lang_item_fn_mut(
+                    req.span,
+                    hir::LangItem::ContractCheckRequires,
+                    &*arena_vec![this; lowered_req],
+                );
+                this.stmt_expr(req.span, precond)
+            } else {
+                let u = lit_unit(this);
+                this.stmt_expr(contract.span, u)
+            };
+
+            let (postcond_checker, result) = if let Some(ens) = contract.ensures {
+                let crate::FnContractLoweringEnsures { expr: ens, fresh_ident } = ens;
+                let lowered_ens: hir::Expr<'hir> = this.lower_expr_mut(&ens);
+                let postcond_checker = this.expr_call_lang_item_fn(
+                    ens.span,
+                    hir::LangItem::ContractBuildCheckEnsures,
+                    &*arena_vec![this; lowered_ens],
+                );
+                let checker_binding_pat = fresh_ident.1;
+                (
+                    this.stmt_let_pat(
+                        None,
+                        ens.span,
+                        Some(postcond_checker),
+                        this.arena.alloc(checker_binding_pat),
+                        hir::LocalSource::Contract,
+                    ),
+                    this.inject_ensures_check(result_ref, ens.span, fresh_ident.0, fresh_ident.2),
+                )
+            } else {
+                let u = lit_unit(this);
+                (this.stmt_expr(contract.span, u), &*result_ref)
+            };
+
+            let block = this.block_all(
+                contract.span,
+                arena_vec![this; precond, postcond_checker],
+                Some(result),
+            );
+            (params, this.expr_block(block))
         })
     }
 
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 893da93085533..2715b3d621522 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -86,6 +86,19 @@ mod path;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
+#[derive(Debug, Clone)]
+struct FnContractLoweringInfo<'hir> {
+    pub span: Span,
+    pub requires: Option<ast::ptr::P<ast::Expr>>,
+    pub ensures: Option<FnContractLoweringEnsures<'hir>>,
+}
+
+#[derive(Debug, Clone)]
+struct FnContractLoweringEnsures<'hir> {
+    expr: ast::ptr::P<ast::Expr>,
+    fresh_ident: (Ident, hir::Pat<'hir>, HirId),
+}
+
 struct LoweringContext<'a, 'hir> {
     tcx: TyCtxt<'hir>,
     resolver: &'a mut ResolverAstLowering,
@@ -100,6 +113,8 @@ struct LoweringContext<'a, 'hir> {
     /// Collect items that were created by lowering the current owner.
     children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>,
 
+    contract: Option<FnContractLoweringInfo<'hir>>,
+
     coroutine_kind: Option<hir::CoroutineKind>,
 
     /// When inside an `async` context, this is the `HirId` of the
@@ -148,6 +163,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             bodies: Vec::new(),
             attrs: SortedMap::default(),
             children: Vec::default(),
+            contract: None,
             current_hir_id_owner: hir::CRATE_OWNER_ID,
             item_local_id_counter: hir::ItemLocalId::ZERO,
             ident_and_label_to_local_id: Default::default(),
@@ -834,12 +850,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
+        let old_contract = self.contract.take();
+
         let catch_scope = self.catch_scope.take();
         let loop_scope = self.loop_scope.take();
         let ret = f(self);
         self.catch_scope = catch_scope;
         self.loop_scope = loop_scope;
 
+        self.contract = old_contract;
+
         self.is_in_loop_condition = was_in_loop_condition;
 
         self.current_item = current_item;
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index ea1f4a6559ac8..0049c5b4823cb 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -917,7 +917,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
             }
-            ItemKind::Fn(func @ box Fn { defaultness, generics: _, sig, body }) => {
+            ItemKind::Fn(func @ box Fn { defaultness, generics: _, sig, contract: _, body }) => {
                 self.check_defaultness(item.span, *defaultness);
 
                 let is_intrinsic =
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 80b99f9448567..62e451fa8764f 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -548,6 +548,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
     gate_all!(unsafe_fields, "`unsafe` fields are experimental");
     gate_all!(unsafe_binders, "unsafe binder types are experimental");
+    gate_all!(contracts, "contracts are incomplete");
+    gate_all!(contracts_internals, "contract internal machinery is for internal use only");
 
     if !visitor.features.never_patterns() {
         if let Some(spans) = spans.get(&sym::never_patterns) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 4cfcaa95233da..c10b5ad34e102 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -650,13 +650,17 @@ impl<'a> State<'a> {
         attrs: &[ast::Attribute],
         func: &ast::Fn,
     ) {
-        let ast::Fn { defaultness, generics, sig, body } = func;
+        let ast::Fn { defaultness, generics, sig, contract, body } = func;
         if body.is_some() {
             self.head("");
         }
         self.print_visibility(vis);
         self.print_defaultness(*defaultness);
         self.print_fn(&sig.decl, sig.header, Some(name), generics);
+        if let Some(contract) = &contract {
+            self.nbsp();
+            self.print_contract(contract);
+        }
         if let Some(body) = body {
             self.nbsp();
             self.print_block_with_attrs(body, attrs);
@@ -665,6 +669,21 @@ impl<'a> State<'a> {
         }
     }
 
+    fn print_contract(&mut self, contract: &ast::FnContract) {
+        if let Some(pred) = &contract.requires {
+            self.word("rustc_requires");
+            self.popen();
+            self.print_expr(pred, FixupContext::default());
+            self.pclose();
+        }
+        if let Some(pred) = &contract.ensures {
+            self.word("rustc_ensures");
+            self.popen();
+            self.print_expr(pred, FixupContext::default());
+            self.pclose();
+        }
+    }
+
     pub(crate) fn print_fn(
         &mut self,
         decl: &ast::FnDecl,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 78aa38e9e48f4..002f6e36cd8b3 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1653,6 +1653,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     ConstraintCategory::SizedBound,
                 );
             }
+            &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
             &Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
 
             Rvalue::ShallowInitBox(operand, ty) => {
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index d2b4e1ca824fd..cffc497860133 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -85,6 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
         defaultness: ast::Defaultness::Final,
         sig,
         generics: Generics::default(),
+        contract: None,
         body,
     }));
 
diff --git a/compiler/rustc_builtin_macros/src/contracts.rs b/compiler/rustc_builtin_macros/src/contracts.rs
new file mode 100644
index 0000000000000..85a30f7bdc9b4
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/contracts.rs
@@ -0,0 +1,176 @@
+#![allow(unused_imports, unused_variables)]
+
+use rustc_ast::token;
+use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
+use rustc_errors::ErrorGuaranteed;
+use rustc_expand::base::{AttrProcMacro, ExtCtxt};
+use rustc_span::Span;
+use rustc_span::symbol::{Ident, Symbol, kw, sym};
+
+pub(crate) struct ExpandRequires;
+
+pub(crate) struct ExpandEnsures;
+
+impl AttrProcMacro for ExpandRequires {
+    fn expand<'cx>(
+        &self,
+        ecx: &'cx mut ExtCtxt<'_>,
+        span: Span,
+        annotation: TokenStream,
+        annotated: TokenStream,
+    ) -> Result<TokenStream, ErrorGuaranteed> {
+        expand_requires_tts(ecx, span, annotation, annotated)
+    }
+}
+
+impl AttrProcMacro for ExpandEnsures {
+    fn expand<'cx>(
+        &self,
+        ecx: &'cx mut ExtCtxt<'_>,
+        span: Span,
+        annotation: TokenStream,
+        annotated: TokenStream,
+    ) -> Result<TokenStream, ErrorGuaranteed> {
+        expand_ensures_tts(ecx, span, annotation, annotated)
+    }
+}
+
+/// Expand the function signature to include the contract clause.
+///
+/// The contracts clause will be injected before the function body and the optional where clause.
+/// For that, we search for the body / where token, and invoke the `inject` callback to generate the
+/// contract clause in the right place.
+///
+// FIXME: this kind of manual token tree munging does not have significant precedent among
+// rustc builtin macros, probably because most builtin macros use direct AST manipulation to
+// accomplish similar goals. But since our attributes need to take arbitrary expressions, and
+// our attribute infrastructure does not yet support mixing a token-tree annotation with an AST
+// annotated, we end up doing token tree manipulation.
+fn expand_contract_clause(
+    ecx: &mut ExtCtxt<'_>,
+    attr_span: Span,
+    annotated: TokenStream,
+    inject: impl FnOnce(&mut TokenStream) -> Result<(), ErrorGuaranteed>,
+) -> Result<TokenStream, ErrorGuaranteed> {
+    let mut new_tts = TokenStream::default();
+    let mut cursor = annotated.iter();
+
+    let is_kw = |tt: &TokenTree, sym: Symbol| {
+        if let TokenTree::Token(token, _) = tt { token.is_ident_named(sym) } else { false }
+    };
+
+    // Find the `fn` keyword to check if this is a function.
+    if cursor
+        .find(|tt| {
+            new_tts.push_tree((*tt).clone());
+            is_kw(tt, kw::Fn)
+        })
+        .is_none()
+    {
+        return Err(ecx
+            .sess
+            .dcx()
+            .span_err(attr_span, "contract annotations can only be used on functions"));
+    }
+
+    // Found the `fn` keyword, now find either the `where` token or the function body.
+    let next_tt = loop {
+        let Some(tt) = cursor.next() else {
+            return Err(ecx.sess.dcx().span_err(
+                attr_span,
+                "contract annotations is only supported in functions with bodies",
+            ));
+        };
+        // If `tt` is the last element. Check if it is the function body.
+        if cursor.peek().is_none() {
+            if let TokenTree::Delimited(_, _, token::Delimiter::Brace, _) = tt {
+                break tt;
+            } else {
+                return Err(ecx.sess.dcx().span_err(
+                    attr_span,
+                    "contract annotations is only supported in functions with bodies",
+                ));
+            }
+        }
+
+        if is_kw(tt, kw::Where) {
+            break tt;
+        }
+        new_tts.push_tree(tt.clone());
+    };
+
+    // At this point, we've transcribed everything from the `fn` through the formal parameter list
+    // and return type declaration, (if any), but `tt` itself has *not* been transcribed.
+    //
+    // Now inject the AST contract form.
+    //
+    inject(&mut new_tts)?;
+
+    // Above we injected the internal AST requires/ensures construct. Now copy over all the other
+    // token trees.
+    new_tts.push_tree(next_tt.clone());
+    while let Some(tt) = cursor.next() {
+        new_tts.push_tree(tt.clone());
+        if cursor.peek().is_none()
+            && !matches!(tt, TokenTree::Delimited(_, _, token::Delimiter::Brace, _))
+        {
+            return Err(ecx.sess.dcx().span_err(
+                attr_span,
+                "contract annotations is only supported in functions with bodies",
+            ));
+        }
+    }
+
+    // Record the span as a contract attribute expansion.
+    // This is used later to stop users from using the extended syntax directly
+    // which is gated via `contracts_internals`.
+    ecx.psess().contract_attribute_spans.push(attr_span);
+
+    Ok(new_tts)
+}
+
+fn expand_requires_tts(
+    _ecx: &mut ExtCtxt<'_>,
+    attr_span: Span,
+    annotation: TokenStream,
+    annotated: TokenStream,
+) -> Result<TokenStream, ErrorGuaranteed> {
+    expand_contract_clause(_ecx, attr_span, annotated, |new_tts| {
+        new_tts.push_tree(TokenTree::Token(
+            token::Token::from_ast_ident(Ident::new(kw::ContractRequires, attr_span)),
+            Spacing::Joint,
+        ));
+        new_tts.push_tree(TokenTree::Token(
+            token::Token::new(token::TokenKind::OrOr, attr_span),
+            Spacing::Alone,
+        ));
+        new_tts.push_tree(TokenTree::Delimited(
+            DelimSpan::from_single(attr_span),
+            DelimSpacing::new(Spacing::JointHidden, Spacing::JointHidden),
+            token::Delimiter::Parenthesis,
+            annotation,
+        ));
+        Ok(())
+    })
+}
+
+fn expand_ensures_tts(
+    _ecx: &mut ExtCtxt<'_>,
+    attr_span: Span,
+    annotation: TokenStream,
+    annotated: TokenStream,
+) -> Result<TokenStream, ErrorGuaranteed> {
+    expand_contract_clause(_ecx, attr_span, annotated, |new_tts| {
+        new_tts.push_tree(TokenTree::Token(
+            token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, attr_span)),
+            Spacing::Joint,
+        ));
+        new_tts.push_tree(TokenTree::Delimited(
+            DelimSpan::from_single(attr_span),
+            DelimSpacing::new(Spacing::JointHidden, Spacing::JointHidden),
+            token::Delimiter::Parenthesis,
+            annotation,
+        ));
+        Ok(())
+    })
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 755a733286cea..0631c5a80fc5e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1034,6 +1034,7 @@ impl<'a> MethodDef<'a> {
                 defaultness,
                 sig,
                 generics: fn_generics,
+                contract: None,
                 body: Some(body_block),
             })),
             tokens: None,
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 8388e9dcafb8c..8fdbbf8e704a9 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -81,6 +81,7 @@ impl AllocFnFactory<'_, '_> {
             defaultness: ast::Defaultness::Final,
             sig,
             generics: Generics::default(),
+            contract: None,
             body,
         }));
         let item = self.cx.item(
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 6987ae95980a6..ca16583a45de7 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -55,6 +55,7 @@ mod trace_macros;
 
 pub mod asm;
 pub mod cmdline_attrs;
+pub mod contracts;
 pub mod proc_macro_harness;
 pub mod standard_library_imports;
 pub mod test_harness;
@@ -137,4 +138,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
 
     let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
     register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })));
+    let requires = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandRequires));
+    register(sym::contracts_requires, requires);
+    let ensures = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandEnsures));
+    register(sym::contracts_ensures, ensures);
 }
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 31b068bd33dae..472e16e62d5b0 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -344,6 +344,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
         defaultness,
         sig,
         generics: ast::Generics::default(),
+        contract: None,
         body: Some(main_body),
     }));
 
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 7a40d236b9288..a2b9e5712e50b 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -868,7 +868,16 @@ fn codegen_stmt<'tcx>(
                         NullOp::UbChecks => {
                             let val = fx.tcx.sess.ub_checks();
                             let val = CValue::by_val(
-                                fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()),
+                                fx.bcx.ins().iconst(types::I8, i64::from(val)),
+                                fx.layout_of(fx.tcx.types.bool),
+                            );
+                            lval.write_cvalue(fx, val);
+                            return;
+                        }
+                        NullOp::ContractChecks => {
+                            let val = fx.tcx.sess.contract_checks();
+                            let val = CValue::by_val(
+                                fx.bcx.ins().iconst(types::I8, i64::from(val)),
                                 fx.layout_of(fx.tcx.types.bool),
                             );
                             lval.write_cvalue(fx, val);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 11eb9651af6c5..f52991b369797 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -127,7 +127,7 @@ fn make_mir_scope<'ll, 'tcx>(
             })
         }
         None => unsafe {
-            llvm::LLVMRustDIBuilderCreateLexicalBlock(
+            llvm::LLVMDIBuilderCreateLexicalBlock(
                 DIB(cx),
                 parent_scope.dbg_scope,
                 file_metadata,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 3a0c7f007bdd2..f497ba95661df 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -931,7 +931,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
 
     unsafe {
         let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile(
-            debug_context.builder,
+            debug_context.builder.as_ref(),
             name_in_debuginfo.as_c_char_ptr(),
             name_in_debuginfo.len(),
             work_dir.as_c_char_ptr(),
@@ -944,7 +944,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
         );
 
         let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
-            debug_context.builder,
+            debug_context.builder.as_ref(),
             dwarf_const::DW_LANG_Rust,
             compile_unit_file,
             producer.as_c_char_ptr(),
@@ -1641,7 +1641,14 @@ pub(crate) fn extend_scope_to_file<'ll>(
     file: &SourceFile,
 ) -> &'ll DILexicalBlock {
     let file_metadata = file_metadata(cx, file);
-    unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
+    unsafe {
+        llvm::LLVMDIBuilderCreateLexicalBlockFile(
+            DIB(cx),
+            scope_metadata,
+            file_metadata,
+            /* Discriminator (default) */ 0u32,
+        )
+    }
 }
 
 fn tuple_field_name(field_index: usize) -> Cow<'static, str> {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index b1ce52667bd6d..496178c6b1d94 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -34,7 +34,7 @@ use crate::builder::Builder;
 use crate::common::{AsCCharPtr, CodegenCx};
 use crate::llvm;
 use crate::llvm::debuginfo::{
-    DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
+    DIArray, DIBuilderBox, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType,
     DIVariable,
 };
 use crate::value::Value;
@@ -61,7 +61,7 @@ const DW_TAG_arg_variable: c_uint = 0x101;
 /// A context object for maintaining all state needed by the debuginfo module.
 pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
     llmod: &'ll llvm::Module,
-    builder: &'ll mut DIBuilder<'ll>,
+    builder: DIBuilderBox<'ll>,
     created_files: RefCell<UnordMap<Option<(StableSourceFileId, SourceFileHash)>, &'ll DIFile>>,
 
     type_map: metadata::TypeMap<'ll, 'tcx>,
@@ -69,18 +69,10 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> {
     recursion_marker_type: OnceCell<&'ll DIType>,
 }
 
-impl Drop for CodegenUnitDebugContext<'_, '_> {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
-        }
-    }
-}
-
 impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
     pub(crate) fn new(llmod: &'ll llvm::Module) -> Self {
         debug!("CodegenUnitDebugContext::new");
-        let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
+        let builder = DIBuilderBox::new(llmod);
         // DIBuilder inherits context from the module, so we'd better use the same one
         CodegenUnitDebugContext {
             llmod,
@@ -93,7 +85,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
     }
 
     pub(crate) fn finalize(&self, sess: &Session) {
-        unsafe { llvm::LLVMRustDIBuilderFinalize(self.builder) };
+        unsafe { llvm::LLVMDIBuilderFinalize(self.builder.as_ref()) };
 
         match sess.target.debuginfo_kind {
             DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym => {
@@ -582,7 +574,7 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             (line, col)
         };
 
-        unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) }
+        unsafe { llvm::LLVMDIBuilderCreateDebugLocation(self.llcx, line, col, scope, inlined_at) }
     }
 
     fn create_vtable_debuginfo(
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
index 33d9bc238903e..b4d639368b005 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, Instance};
 
 use super::utils::{DIB, debug_context};
-use crate::common::{AsCCharPtr, CodegenCx};
+use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::DIScope;
 
@@ -33,12 +33,12 @@ pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'l
     };
 
     let scope = unsafe {
-        llvm::LLVMRustDIBuilderCreateNameSpace(
+        llvm::LLVMDIBuilderCreateNameSpace(
             DIB(cx),
             parent_scope,
-            namespace_name_string.as_c_char_ptr(),
+            namespace_name_string.as_ptr(),
             namespace_name_string.len(),
-            false, // ExportSymbols (only relevant for C++ anonymous namespaces)
+            llvm::False, // ExportSymbols (only relevant for C++ anonymous namespaces)
         )
     };
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index 6e84129347787..cc1d504b43017 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -41,7 +41,7 @@ pub(crate) fn debug_context<'a, 'll, 'tcx>(
 #[inline]
 #[allow(non_snake_case)]
 pub(crate) fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> {
-    cx.dbg_cx.as_ref().unwrap().builder
+    cx.dbg_cx.as_ref().unwrap().builder.as_ref()
 }
 
 pub(crate) fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index cc7c5231aca58..5c53a419a6ccc 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1,3 +1,15 @@
+//! Bindings to the LLVM-C API (`LLVM*`), and to our own `extern "C"` wrapper
+//! functions around the unstable LLVM C++ API (`LLVMRust*`).
+//!
+//! ## Passing pointer/length strings as `*const c_uchar`
+//!
+//! Normally it's a good idea for Rust-side bindings to match the corresponding
+//! C-side function declarations as closely as possible. But when passing `&str`
+//! or `&[u8]` data as a pointer/length pair, it's more convenient to declare
+//! the Rust-side pointer as `*const c_uchar` instead of `*const c_char`.
+//! Both pointer types have the same ABI, and using `*const c_uchar` avoids
+//! the need for an extra cast from `*const u8` on the Rust side.
+
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 
@@ -5,17 +17,18 @@ use std::fmt::Debug;
 use std::marker::PhantomData;
 use std::ptr;
 
-use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
+use bitflags::bitflags;
+use libc::{c_char, c_int, c_uchar, c_uint, c_ulonglong, c_void, size_t};
 use rustc_macros::TryFromU32;
 use rustc_target::spec::SymbolVisibility;
 
 use super::RustString;
 use super::debuginfo::{
     DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
-    DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DILocation, DINameSpace,
-    DISPFlags, DIScope, DISubprogram, DISubrange, DITemplateTypeParameter, DIType, DIVariable,
-    DebugEmissionKind, DebugNameTableKind,
+    DIFile, DIFlags, DIGlobalVariableExpression, DILocation, DISPFlags, DIScope, DISubprogram,
+    DISubrange, DITemplateTypeParameter, DIType, DIVariable, DebugEmissionKind, DebugNameTableKind,
 };
+use crate::llvm;
 
 /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
 /// which has a different ABI from Rust or C++ `bool`.
@@ -789,12 +802,50 @@ pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void
 pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
 
 pub mod debuginfo {
+    use std::ptr;
+
     use bitflags::bitflags;
 
     use super::{InvariantOpaque, Metadata};
+    use crate::llvm::{self, Module};
 
+    /// Opaque target type for references to an LLVM debuginfo builder.
+    ///
+    /// `&'_ DIBuilder<'ll>` corresponds to `LLVMDIBuilderRef`, which is the
+    /// LLVM-C wrapper for `DIBuilder *`.
+    ///
+    /// Debuginfo builders are created and destroyed during codegen, so the
+    /// builder reference typically has a shorter lifetime than the LLVM
+    /// session (`'ll`) that it participates in.
     #[repr(C)]
-    pub struct DIBuilder<'a>(InvariantOpaque<'a>);
+    pub struct DIBuilder<'ll>(InvariantOpaque<'ll>);
+
+    /// Owning pointer to a `DIBuilder<'ll>` that will dispose of the builder
+    /// when dropped. Use `.as_ref()` to get the underlying `&DIBuilder`
+    /// needed for debuginfo FFI calls.
+    pub(crate) struct DIBuilderBox<'ll> {
+        raw: ptr::NonNull<DIBuilder<'ll>>,
+    }
+
+    impl<'ll> DIBuilderBox<'ll> {
+        pub(crate) fn new(llmod: &'ll Module) -> Self {
+            let raw = unsafe { llvm::LLVMCreateDIBuilder(llmod) };
+            let raw = ptr::NonNull::new(raw).unwrap();
+            Self { raw }
+        }
+
+        pub(crate) fn as_ref(&self) -> &DIBuilder<'ll> {
+            // SAFETY: This is an owning pointer, so `&DIBuilder` is valid
+            // for as long as `&self` is.
+            unsafe { self.raw.as_ref() }
+        }
+    }
+
+    impl<'ll> Drop for DIBuilderBox<'ll> {
+        fn drop(&mut self) {
+            unsafe { llvm::LLVMDisposeDIBuilder(self.raw) };
+        }
+    }
 
     pub type DIDescriptor = Metadata;
     pub type DILocation = Metadata;
@@ -914,7 +965,6 @@ pub mod debuginfo {
     }
 }
 
-use bitflags::bitflags;
 // These values **must** match with LLVMRustAllocKindFlags
 bitflags! {
     #[repr(transparent)]
@@ -1672,6 +1722,50 @@ unsafe extern "C" {
     ) -> &'a Value;
 }
 
+// FFI bindings for `DIBuilder` functions in the LLVM-C API.
+// Try to keep these in the same order as in `llvm/include/llvm-c/DebugInfo.h`.
+//
+// FIXME(#134001): Audit all `Option` parameters, especially in lists, to check
+// that they really are nullable on the C/C++ side. LLVM doesn't appear to
+// actually document which ones are nullable.
+unsafe extern "C" {
+    pub(crate) fn LLVMCreateDIBuilder<'ll>(M: &'ll Module) -> *mut DIBuilder<'ll>;
+    pub(crate) fn LLVMDisposeDIBuilder<'ll>(Builder: ptr::NonNull<DIBuilder<'ll>>);
+
+    pub(crate) fn LLVMDIBuilderFinalize<'ll>(Builder: &DIBuilder<'ll>);
+
+    pub(crate) fn LLVMDIBuilderCreateNameSpace<'ll>(
+        Builder: &DIBuilder<'ll>,
+        ParentScope: Option<&'ll Metadata>,
+        Name: *const c_uchar,
+        NameLen: size_t,
+        ExportSymbols: llvm::Bool,
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateLexicalBlock<'ll>(
+        Builder: &DIBuilder<'ll>,
+        Scope: &'ll Metadata,
+        File: &'ll Metadata,
+        Line: c_uint,
+        Column: c_uint,
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateLexicalBlockFile<'ll>(
+        Builder: &DIBuilder<'ll>,
+        Scope: &'ll Metadata,
+        File: &'ll Metadata,
+        Discriminator: c_uint, // (optional "DWARF path discriminator"; default is 0)
+    ) -> &'ll Metadata;
+
+    pub(crate) fn LLVMDIBuilderCreateDebugLocation<'ll>(
+        Ctx: &'ll Context,
+        Line: c_uint,
+        Column: c_uint,
+        Scope: &'ll Metadata,
+        InlinedAt: Option<&'ll Metadata>,
+    ) -> &'ll Metadata;
+}
+
 #[link(name = "llvm-wrapper", kind = "static")]
 unsafe extern "C" {
     pub fn LLVMRustInstallErrorHandlers();
@@ -1939,12 +2033,6 @@ unsafe extern "C" {
         ValueLen: size_t,
     );
 
-    pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
-
-    pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>);
-
-    pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder<'_>);
-
     pub fn LLVMRustDIBuilderCreateCompileUnit<'a>(
         Builder: &DIBuilder<'a>,
         Lang: c_uint,
@@ -2107,20 +2195,6 @@ unsafe extern "C" {
         Type: &'a DIType,
     ) -> &'a DIDerivedType;
 
-    pub fn LLVMRustDIBuilderCreateLexicalBlock<'a>(
-        Builder: &DIBuilder<'a>,
-        Scope: &'a DIScope,
-        File: &'a DIFile,
-        Line: c_uint,
-        Col: c_uint,
-    ) -> &'a DILexicalBlock;
-
-    pub fn LLVMRustDIBuilderCreateLexicalBlockFile<'a>(
-        Builder: &DIBuilder<'a>,
-        Scope: &'a DIScope,
-        File: &'a DIFile,
-    ) -> &'a DILexicalBlock;
-
     pub fn LLVMRustDIBuilderCreateStaticVariable<'a>(
         Builder: &DIBuilder<'a>,
         Context: Option<&'a DIScope>,
@@ -2245,14 +2319,6 @@ unsafe extern "C" {
         Ty: &'a DIType,
     ) -> &'a DITemplateTypeParameter;
 
-    pub fn LLVMRustDIBuilderCreateNameSpace<'a>(
-        Builder: &DIBuilder<'a>,
-        Scope: Option<&'a DIScope>,
-        Name: *const c_char,
-        NameLen: size_t,
-        ExportSymbols: bool,
-    ) -> &'a DINameSpace;
-
     pub fn LLVMRustDICompositeTypeReplaceArrays<'a>(
         Builder: &DIBuilder<'a>,
         CompositeType: &'a DIType,
@@ -2260,12 +2326,6 @@ unsafe extern "C" {
         Params: Option<&'a DIArray>,
     );
 
-    pub fn LLVMRustDIBuilderCreateDebugLocation<'a>(
-        Line: c_uint,
-        Column: c_uint,
-        Scope: &'a DIScope,
-        InlinedAt: Option<&'a DILocation>,
-    ) -> &'a DILocation;
     pub fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
         Location: &'a DILocation,
         BD: c_uint,
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 85de3238b3e77..27cb7883b9a6c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -741,6 +741,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         let val = bx.tcx().sess.ub_checks();
                         bx.cx().const_bool(val)
                     }
+                    mir::NullOp::ContractChecks => {
+                        let val = bx.tcx().sess.contract_checks();
+                        bx.cx().const_bool(val)
+                    }
                 };
                 let tcx = self.cx.tcx();
                 OperandRef {
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index e8052a3c83a1f..d0ce027ec2b71 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -675,7 +675,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             Rvalue::Cast(_, _, _) => {}
 
             Rvalue::NullaryOp(
-                NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbChecks,
+                NullOp::SizeOf
+                | NullOp::AlignOf
+                | NullOp::OffsetOf(_)
+                | NullOp::UbChecks
+                | NullOp::ContractChecks,
                 _,
             ) => {}
             Rvalue::ShallowInitBox(_, _) => {}
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 8f6b15b8df012..1a799f5dea5b5 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -293,6 +293,9 @@ pub trait Machine<'tcx>: Sized {
     /// Determines the result of a `NullaryOp::UbChecks` invocation.
     fn ub_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>;
 
+    /// Determines the result of a `NullaryOp::ContractChecks` invocation.
+    fn contract_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>;
+
     /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction.
     /// You can use this to detect long or endlessly running programs.
     #[inline]
@@ -679,6 +682,13 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
         interp_ok(true)
     }
 
+    #[inline(always)]
+    fn contract_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> {
+        // We can't look at `tcx.sess` here as that can differ across crates, which can lead to
+        // unsound differences in evaluating the same constant at different instantiation sites.
+        interp_ok(true)
+    }
+
     #[inline(always)]
     fn adjust_global_allocation<'b>(
         _ecx: &InterpCx<$tcx, Self>,
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 5fa632fc57aaf..899670aeb62da 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -537,6 +537,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 ImmTy::from_uint(val, usize_layout())
             }
             UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx),
+            ContractChecks => ImmTy::from_bool(M::contract_checks(self)?, *self.tcx),
         })
     }
 }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e0543977e98d8..67eb96e4d56ad 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -19,6 +19,7 @@ const GATED_CFGS: &[GatedCfg] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
     (sym::overflow_checks, sym::cfg_overflow_checks, Features::cfg_overflow_checks),
     (sym::ub_checks, sym::cfg_ub_checks, Features::cfg_ub_checks),
+    (sym::contract_checks, sym::cfg_contract_checks, Features::cfg_contract_checks),
     (sym::target_thread_local, sym::cfg_target_thread_local, Features::cfg_target_thread_local),
     (
         sym::target_has_atomic_equal_alignment,
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index f5761da60f2c2..aff5514907389 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -403,6 +403,8 @@ declare_features! (
     (unstable, c_variadic, "1.34.0", Some(44930)),
     /// Allows the use of `#[cfg(<true/false>)]`.
     (unstable, cfg_boolean_literals, "1.83.0", Some(131204)),
+    /// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
+    (unstable, cfg_contract_checks, "CURRENT_RUSTC_VERSION", Some(128044)),
     /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
     (unstable, cfg_overflow_checks, "1.71.0", Some(111466)),
     /// Provides the relocation model information as cfg entry
@@ -445,6 +447,10 @@ declare_features! (
     (unstable, const_trait_impl, "1.42.0", Some(67792)),
     /// Allows the `?` operator in const contexts.
     (unstable, const_try, "1.56.0", Some(74935)),
+    /// Allows use of contracts attributes.
+    (incomplete, contracts, "CURRENT_RUSTC_VERSION", Some(128044)),
+    /// Allows access to internal machinery used to implement contracts.
+    (internal, contracts_internals, "CURRENT_RUSTC_VERSION", Some(128044)),
     /// Allows coroutines to be cloned.
     (unstable, coroutine_clone, "1.65.0", Some(95360)),
     /// Allows defining coroutines.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index af2f86b67e007..8bc09f631cf1e 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2598,6 +2598,8 @@ pub enum LocalSource {
     /// A desugared `expr = expr`, where the LHS is a tuple, struct, array or underscore expression.
     /// The span is that of the `=` sign.
     AssignDesugar(Span),
+    /// A contract `#[ensures(..)]` attribute injects a let binding for the check that runs at point of return.
+    Contract,
 }
 
 /// Hints at the original code for a `match _ { .. }`.
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index d9759580e8fdc..75898cbec14b8 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -418,6 +418,10 @@ language_item_table! {
 
     String,                  sym::String,              string,                     Target::Struct,         GenericRequirement::None;
     CStr,                    sym::CStr,                c_str,                      Target::Struct,         GenericRequirement::None;
+
+    // Experimental lang items for implementing contract pre- and post-condition checking.
+    ContractBuildCheckEnsures, sym::contract_build_check_ensures, contract_build_check_ensures_fn, Target::Fn, GenericRequirement::None;
+    ContractCheckRequires,     sym::contract_check_requires,      contract_check_requires_fn,      Target::Fn, GenericRequirement::None;
 }
 
 pub enum GenericRequirement {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index cf3d489730425..e641fb0fb62e6 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -132,6 +132,9 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
         | sym::aggregate_raw_ptr
         | sym::ptr_metadata
         | sym::ub_checks
+        | sym::contract_checks
+        | sym::contract_check_requires
+        | sym::contract_check_ensures
         | sym::fadd_algebraic
         | sym::fsub_algebraic
         | sym::fmul_algebraic
@@ -219,6 +222,16 @@ pub fn check_intrinsic_type(
             }
         };
         (n_tps, 0, 0, inputs, output, hir::Safety::Unsafe)
+    } else if intrinsic_name == sym::contract_check_ensures {
+        // contract_check_ensures::<'a, Ret, C>(&'a Ret, C)
+        // where C: impl Fn(&'a Ret) -> bool,
+        //
+        // so: two type params, one lifetime param, 0 const params, two inputs, no return
+
+        let p = generics.param_at(0, tcx);
+        let r = ty::Region::new_early_param(tcx, p.to_early_bound_region_data());
+        let ref_ret = Ty::new_imm_ref(tcx, r, param(1));
+        (2, 1, 0, vec![ref_ret, param(2)], tcx.types.unit, hir::Safety::Safe)
     } else {
         let safety = intrinsic_operation_unsafety(tcx, intrinsic_id);
         let (n_tps, n_cts, inputs, output) = match intrinsic_name {
@@ -610,6 +623,11 @@ pub fn check_intrinsic_type(
 
             sym::box_new => (1, 0, vec![param(0)], Ty::new_box(tcx, param(0))),
 
+            // contract_checks() -> bool
+            sym::contract_checks => (0, 0, Vec::new(), tcx.types.bool),
+            // contract_check_requires::<C>(C) -> bool, where C: impl Fn() -> bool
+            sym::contract_check_requires => (1, 0, vec![param(0)], tcx.types.unit),
+
             sym::simd_eq
             | sym::simd_ne
             | sym::simd_lt
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index a519e177fbccd..f7bc21cc5260d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -269,6 +269,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // diverging expression (e.g. it arose from desugaring of `try { return }`),
             // we skip issuing a warning because it is autogenerated code.
             ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {}
+            // Likewise, do not lint unreachable code injected via contracts desugaring.
+            ExprKind::Call(..) if expr.span.is_desugaring(DesugaringKind::Contract) => {}
             ExprKind::Call(callee, _) => self.warn_if_unreachable(expr.hir_id, callee.span, "call"),
             ExprKind::MethodCall(segment, ..) => {
                 self.warn_if_unreachable(expr.hir_id, segment.ident.span, "call")
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index bbe653714962e..e90474cabb420 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -13,7 +13,7 @@ use rustc_hir::{ExprKind, HirId, Node, QPath};
 use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
 use rustc_hir_analysis::check::potentially_plural_count;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_index::IndexVec;
+use rustc_index::{Idx, IndexVec};
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::error::TypeError;
@@ -21,7 +21,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::Session;
-use rustc_span::{DUMMY_SP, Ident, Span, kw, sym};
+use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
 use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
@@ -126,7 +126,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Err(guar) => Err(guar),
         };
         if let Err(guar) = has_error {
-            let err_inputs = self.err_args(args_no_rcvr.len(), guar);
+            let err_inputs = self.err_args(
+                method.map_or(args_no_rcvr.len(), |method| method.sig.inputs().len() - 1),
+                guar,
+            );
             let err_output = Ty::new_error(self.tcx, guar);
 
             let err_inputs = match tuple_arguments {
@@ -2374,11 +2377,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let check_for_matched_generics = || {
                     if matched_inputs.iter().any(|x| x.is_some())
-                        && params_with_generics.iter().any(|x| x.1.is_some())
+                        && params_with_generics.iter().any(|(x, _)| x.is_some())
                     {
-                        for &(idx, generic, _) in &params_with_generics {
+                        for (idx, (generic, _)) in params_with_generics.iter_enumerated() {
                             // Param has to have a generic and be matched to be relevant
-                            if matched_inputs[idx.into()].is_none() {
+                            if matched_inputs[idx].is_none() {
                                 continue;
                             }
 
@@ -2386,10 +2389,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 continue;
                             };
 
-                            for unmatching_idx in idx + 1..params_with_generics.len() {
-                                if matched_inputs[unmatching_idx.into()].is_none()
+                            for unmatching_idx in
+                                idx.plus(1)..ExpectedIdx::from_usize(params_with_generics.len())
+                            {
+                                if matched_inputs[unmatching_idx].is_none()
                                     && let Some(unmatched_idx_param_generic) =
-                                        params_with_generics[unmatching_idx].1
+                                        params_with_generics[unmatching_idx].0
                                     && unmatched_idx_param_generic.name.ident()
                                         == generic.name.ident()
                                 {
@@ -2404,61 +2409,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let check_for_matched_generics = check_for_matched_generics();
 
-                for &(idx, generic_param, param) in
-                    params_with_generics.iter().filter(|&(idx, _, _)| {
+                for (idx, &(generic_param, param)) in
+                    params_with_generics.iter_enumerated().filter(|&(idx, _)| {
                         check_for_matched_generics
-                            || expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
+                            || expected_idx
+                                .is_none_or(|expected_idx| expected_idx == idx.as_usize())
                     })
                 {
                     let Some(generic_param) = generic_param else {
-                        spans.push_span_label(param.span, "");
+                        spans.push_span_label(param.span(), "");
                         continue;
                     };
 
-                    let other_params_matched: Vec<(usize, &hir::Param<'_>)> = params_with_generics
-                        .iter()
-                        .filter(|(other_idx, other_generic_param, _)| {
-                            if *other_idx == idx {
-                                return false;
-                            }
-                            let Some(other_generic_param) = other_generic_param else {
-                                return false;
-                            };
-                            if matched_inputs[idx.into()].is_none()
-                                && matched_inputs[(*other_idx).into()].is_none()
-                            {
-                                return false;
-                            }
-                            if matched_inputs[idx.into()].is_some()
-                                && matched_inputs[(*other_idx).into()].is_some()
-                            {
-                                return false;
-                            }
-                            other_generic_param.name.ident() == generic_param.name.ident()
-                        })
-                        .map(|&(other_idx, _, other_param)| (other_idx, other_param))
-                        .collect();
+                    let other_params_matched: Vec<(ExpectedIdx, FnParam<'_>)> =
+                        params_with_generics
+                            .iter_enumerated()
+                            .filter(|&(other_idx, &(other_generic_param, _))| {
+                                if other_idx == idx {
+                                    return false;
+                                }
+                                let Some(other_generic_param) = other_generic_param else {
+                                    return false;
+                                };
+                                if matched_inputs[idx].is_none()
+                                    && matched_inputs[other_idx].is_none()
+                                {
+                                    return false;
+                                }
+                                if matched_inputs[idx].is_some()
+                                    && matched_inputs[other_idx].is_some()
+                                {
+                                    return false;
+                                }
+                                other_generic_param.name.ident() == generic_param.name.ident()
+                            })
+                            .map(|(other_idx, &(_, other_param))| (other_idx, other_param))
+                            .collect();
 
                     if !other_params_matched.is_empty() {
                         let other_param_matched_names: Vec<String> = other_params_matched
                             .iter()
                             .map(|(idx, other_param)| {
-                                if let hir::PatKind::Binding(_, _, ident, _) = other_param.pat.kind
-                                {
-                                    format!("`{ident}`")
+                                if let Some(name) = other_param.name() {
+                                    format!("`{name}`")
                                 } else {
-                                    format!("parameter #{}", idx + 1)
+                                    format!("parameter #{}", idx.as_u32() + 1)
                                 }
                             })
                             .collect();
 
                         let matched_ty = self
-                            .resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
+                            .resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
                             .sort_string(self.tcx);
 
-                        if matched_inputs[idx.into()].is_some() {
+                        if matched_inputs[idx].is_some() {
                             spans.push_span_label(
-                                param.span,
+                                param.span(),
                                 format!(
                                     "{} need{} to match the {} type of this parameter",
                                     listify(&other_param_matched_names, |n| n.to_string())
@@ -2473,7 +2479,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             );
                         } else {
                             spans.push_span_label(
-                                param.span,
+                                param.span(),
                                 format!(
                                     "this parameter needs to match the {} type of {}",
                                     matched_ty,
@@ -2484,7 +2490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                         generics_with_unmatched_params.push(generic_param);
                     } else {
-                        spans.push_span_label(param.span, "");
+                        spans.push_span_label(param.span(), "");
                     }
                 }
 
@@ -2502,19 +2508,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     })
                 {
                     let param_idents_matching: Vec<String> = params_with_generics
-                        .iter()
-                        .filter(|(_, generic, _)| {
+                        .iter_enumerated()
+                        .filter(|&(_, &(generic, _))| {
                             if let Some(generic) = generic {
                                 generic.name.ident() == generic_param.name.ident()
                             } else {
                                 false
                             }
                         })
-                        .map(|(idx, _, param)| {
-                            if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind {
-                                format!("`{ident}`")
+                        .map(|(idx, &(_, param))| {
+                            if let Some(name) = param.name() {
+                                format!("`{name}`")
                             } else {
-                                format!("parameter #{}", idx + 1)
+                                format!("parameter #{}", idx.as_u32() + 1)
                             }
                         })
                         .collect();
@@ -2607,12 +2613,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let Some(params_with_generics) = self.get_hir_params_with_generics(def_id, is_method) {
             debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
-            for &(idx, generic_param, _) in &params_with_generics {
-                if matched_inputs[idx.into()].is_none() {
+            for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
+                if matched_inputs[idx].is_none() {
                     continue;
                 }
 
-                let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.into()) else {
+                let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx())
+                else {
                     continue;
                 };
 
@@ -2620,32 +2627,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     continue;
                 };
 
-                let mut idxs_matched: Vec<usize> = vec![];
-                for &(other_idx, _, _) in
-                    params_with_generics.iter().filter(|&&(other_idx, other_generic_param, _)| {
+                let idxs_matched = params_with_generics
+                    .iter_enumerated()
+                    .filter(|&(other_idx, (other_generic_param, _))| {
                         if other_idx == idx {
                             return false;
                         }
                         let Some(other_generic_param) = other_generic_param else {
                             return false;
                         };
-                        if matched_inputs[other_idx.into()].is_some() {
+                        if matched_inputs[other_idx].is_some() {
                             return false;
                         }
                         other_generic_param.name.ident() == generic_param.name.ident()
                     })
-                {
-                    idxs_matched.push(other_idx);
-                }
+                    .count();
 
-                if idxs_matched.is_empty() {
+                if idxs_matched == 0 {
                     continue;
                 }
 
                 let expected_display_type = self
                     .resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
                     .sort_string(self.tcx);
-                let label = if idxs_matched.len() == params_with_generics.len() - 1 {
+                let label = if idxs_matched == params_with_generics.len() - 1 {
                     format!(
                         "expected all arguments to be this {} type because they need to match the type of this parameter",
                         expected_display_type
@@ -2664,62 +2669,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Returns the parameters of a function, with their generic parameters if those are the full
-    /// type of that parameter. Returns `None` if the function body is unavailable (eg is an instrinsic).
+    /// type of that parameter. Returns `None` if the function has no generics or the body is
+    /// unavailable (eg is an instrinsic).
     fn get_hir_params_with_generics(
         &self,
         def_id: DefId,
         is_method: bool,
-    ) -> Option<Vec<(usize, Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
-        let fn_node = self.tcx.hir().get_if_local(def_id)?;
-        let fn_decl = fn_node.fn_decl()?;
-
-        let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
-            .inputs
-            .into_iter()
-            .skip(if is_method { 1 } else { 0 })
-            .map(|param| {
-                if let hir::TyKind::Path(QPath::Resolved(
-                    _,
-                    hir::Path { res: Res::Def(_, res_def_id), .. },
-                )) = param.kind
-                {
-                    fn_node
-                        .generics()
-                        .into_iter()
-                        .flat_map(|generics| generics.params)
-                        .find(|param| &param.def_id.to_def_id() == res_def_id)
-                } else {
-                    None
-                }
+    ) -> Option<IndexVec<ExpectedIdx, (Option<&hir::GenericParam<'_>>, FnParam<'_>)>> {
+        let (sig, generics, body_id, param_names) = match self.tcx.hir().get_if_local(def_id)? {
+            hir::Node::TraitItem(&hir::TraitItem {
+                generics,
+                kind: hir::TraitItemKind::Fn(sig, trait_fn),
+                ..
+            }) => match trait_fn {
+                hir::TraitFn::Required(params) => (sig, generics, None, Some(params)),
+                hir::TraitFn::Provided(body) => (sig, generics, Some(body), None),
+            },
+            hir::Node::ImplItem(&hir::ImplItem {
+                generics,
+                kind: hir::ImplItemKind::Fn(sig, body),
+                ..
             })
-            .collect();
-
-        let mut params: Vec<&hir::Param<'_>> = self
-            .tcx
-            .hir()
-            .body(fn_node.body_id()?)
-            .params
-            .into_iter()
-            .skip(if is_method { 1 } else { 0 })
-            .collect();
-
-        // The surrounding code expects variadic functions to not have a parameter representing
-        // the "..." parameter. This is already true of the FnDecl but not of the body params, so
-        // we drop it if it exists.
+            | hir::Node::Item(&hir::Item {
+                kind: hir::ItemKind::Fn { sig, generics, body, .. },
+                ..
+            }) => (sig, generics, Some(body), None),
+            _ => return None,
+        };
 
-        if fn_decl.c_variadic {
-            params.pop();
+        // Make sure to remove both the receiver and variadic argument. Both are removed
+        // when matching parameter types.
+        let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| {
+            if let hir::TyKind::Path(QPath::Resolved(
+                _,
+                &hir::Path { res: Res::Def(_, res_def_id), .. },
+            )) = param.kind
+            {
+                generics.params.iter().find(|param| param.def_id.to_def_id() == res_def_id)
+            } else {
+                None
+            }
+        });
+        match (body_id, param_names) {
+            (Some(_), Some(_)) | (None, None) => unreachable!(),
+            (Some(body), None) => {
+                let params = self.tcx.hir().body(body).params;
+                let params =
+                    params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
+                debug_assert_eq!(params.len(), fn_inputs.len());
+                Some(fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect())
+            }
+            (None, Some(params)) => {
+                let params = params.get(is_method as usize..)?;
+                debug_assert_eq!(params.len(), fn_inputs.len());
+                Some(fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect())
+            }
         }
-
-        debug_assert_eq!(params.len(), generic_params.len());
-        Some(
-            generic_params
-                .into_iter()
-                .zip(params)
-                .enumerate()
-                .map(|(a, (b, c))| (a, b, c))
-                .collect(),
-        )
     }
 }
 
@@ -2742,3 +2747,27 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> {
         hir::intravisit::walk_expr(self, ex);
     }
 }
+
+#[derive(Clone, Copy)]
+enum FnParam<'hir> {
+    Param(&'hir hir::Param<'hir>),
+    Name(&'hir Ident),
+}
+impl FnParam<'_> {
+    fn span(&self) -> Span {
+        match self {
+            Self::Param(x) => x.span,
+            Self::Name(x) => x.span,
+        }
+    }
+
+    fn name(&self) -> Option<Symbol> {
+        match self {
+            Self::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => {
+                Some(ident.name)
+            }
+            Self::Name(x) if x.name != kw::Empty => Some(x.name),
+            _ => None,
+        }
+    }
+}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 7ff316ba83a61..76ad7fc890911 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1003,10 +1003,6 @@ extern "C" void LLVMRustDIBuilderDispose(LLVMDIBuilderRef Builder) {
   delete unwrap(Builder);
 }
 
-extern "C" void LLVMRustDIBuilderFinalize(LLVMDIBuilderRef Builder) {
-  unwrap(Builder)->finalize();
-}
-
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
     LLVMDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
     const char *Producer, size_t ProducerLen, bool isOptimized,
@@ -1183,20 +1179,6 @@ LLVMRustDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag,
       unwrap(Builder)->createQualifiedType(Tag, unwrapDI<DIType>(Type)));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Builder,
-                                    LLVMMetadataRef Scope, LLVMMetadataRef File,
-                                    unsigned Line, unsigned Col) {
-  return wrap(unwrap(Builder)->createLexicalBlock(
-      unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Col));
-}
-
-extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlockFile(
-    LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef File) {
-  return wrap(unwrap(Builder)->createLexicalBlockFile(
-      unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File)));
-}
-
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
     LLVMDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name,
     size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
@@ -1325,14 +1307,6 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
       unwrapDI<DIType>(Ty), IsDefault));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder,
-                                 LLVMMetadataRef Scope, const char *Name,
-                                 size_t NameLen, bool ExportSymbols) {
-  return wrap(unwrap(Builder)->createNameSpace(
-      unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols));
-}
-
 extern "C" void LLVMRustDICompositeTypeReplaceArrays(
     LLVMDIBuilderRef Builder, LLVMMetadataRef CompositeTy,
     LLVMMetadataRef Elements, LLVMMetadataRef Params) {
@@ -1341,16 +1315,6 @@ extern "C" void LLVMRustDICompositeTypeReplaceArrays(
                                  DINodeArray(unwrap<MDTuple>(Params)));
 }
 
-extern "C" LLVMMetadataRef
-LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
-                                     LLVMMetadataRef ScopeRef,
-                                     LLVMMetadataRef InlinedAt) {
-  MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
-  DILocation *Loc = DILocation::get(Scope->getContext(), Line, Column, Scope,
-                                    unwrapDIPtr<MDNode>(InlinedAt));
-  return wrap(Loc);
-}
-
 extern "C" LLVMMetadataRef
 LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location,
                                              unsigned BD) {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index aa8ec3aff040a..3007b78749683 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1104,6 +1104,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                     NullOp::AlignOf => write!(fmt, "AlignOf({t})"),
                     NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"),
                     NullOp::UbChecks => write!(fmt, "UbChecks()"),
+                    NullOp::ContractChecks => write!(fmt, "ContractChecks()"),
                 }
             }
             ThreadLocalRef(did) => ty::tls::with(|tcx| {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 2da25f480c65f..9cec8d832dd14 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1591,6 +1591,9 @@ pub enum NullOp<'tcx> {
     /// Returns whether we should perform some UB-checking at runtime.
     /// See the `ub_checks` intrinsic docs for details.
     UbChecks,
+    /// Returns whether we should perform contract-checking at runtime.
+    /// See the `contract_checks` intrinsic docs for details.
+    ContractChecks,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 49449426fa408..af23c8b2ea76d 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -230,7 +230,8 @@ impl<'tcx> Rvalue<'tcx> {
             Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
                 tcx.types.usize
             }
-            Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
+            Rvalue::NullaryOp(NullOp::ContractChecks, _)
+            | Rvalue::NullaryOp(NullOp::UbChecks, _) => tcx.types.bool,
             Rvalue::Aggregate(ref ak, ref ops) => match **ak {
                 AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
                 AggregateKind::Tuple => {
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index c9df027687ab9..e858b629ab14b 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -6,9 +6,9 @@ use rustc_middle::ty;
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
 use tracing::debug;
 
-use crate::thir::cx::Cx;
+use crate::thir::cx::ThirBuildCx;
 
-impl<'tcx> Cx<'tcx> {
+impl<'tcx> ThirBuildCx<'tcx> {
     pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId {
         // We have to eagerly lower the "spine" of the statements
         // in order to get the lexical scoping correctly.
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 795ac6b4bea54..54da6924db444 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -21,10 +21,9 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, sym};
 use tracing::{debug, info, instrument, trace};
 
-use crate::thir::cx::Cx;
-use crate::thir::util::UserAnnotatedTyHelpers;
+use crate::thir::cx::ThirBuildCx;
 
-impl<'tcx> Cx<'tcx> {
+impl<'tcx> ThirBuildCx<'tcx> {
     /// Create a THIR expression for the given HIR expression. This expands all
     /// adjustments and directly adds the type information from the
     /// `typeck_results`. See the [dev-guide] for more details.
@@ -142,9 +141,9 @@ impl<'tcx> Cx<'tcx> {
             Adjust::Deref(Some(deref)) => {
                 // We don't need to do call adjust_span here since
                 // deref coercions always start with a built-in deref.
-                let call_def_id = deref.method_call(self.tcx());
+                let call_def_id = deref.method_call(self.tcx);
                 let overloaded_callee =
-                    Ty::new_fn_def(self.tcx(), call_def_id, self.tcx().mk_args(&[expr.ty.into()]));
+                    Ty::new_fn_def(self.tcx, call_def_id, self.tcx.mk_args(&[expr.ty.into()]));
 
                 expr = Expr {
                     temp_lifetime,
@@ -253,10 +252,10 @@ impl<'tcx> Cx<'tcx> {
 
         // Check to see if this cast is a "coercion cast", where the cast is actually done
         // using a coercion (or is a no-op).
-        if self.typeck_results().is_coercion_cast(source.hir_id) {
+        if self.typeck_results.is_coercion_cast(source.hir_id) {
             // Convert the lexpr to a vexpr.
             ExprKind::Use { source: self.mirror_expr(source) }
-        } else if self.typeck_results().expr_ty(source).is_ref() {
+        } else if self.typeck_results.expr_ty(source).is_ref() {
             // Special cased so that we can type check that the element
             // type of the source matches the pointed to type of the
             // destination.
@@ -266,8 +265,8 @@ impl<'tcx> Cx<'tcx> {
                 is_from_as_cast: true,
             }
         } else if let hir::ExprKind::Path(ref qpath) = source.kind
-            && let res = self.typeck_results().qpath_res(qpath, source.hir_id)
-            && let ty = self.typeck_results().node_type(source.hir_id)
+            && let res = self.typeck_results.qpath_res(qpath, source.hir_id)
+            && let ty = self.typeck_results.node_type(source.hir_id)
             && let ty::Adt(adt_def, args) = ty.kind()
             && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res
         {
@@ -330,7 +329,7 @@ impl<'tcx> Cx<'tcx> {
     #[instrument(level = "debug", skip(self), ret)]
     fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
         let tcx = self.tcx;
-        let expr_ty = self.typeck_results().expr_ty(expr);
+        let expr_ty = self.typeck_results.expr_ty(expr);
         let (temp_lifetime, backwards_incompatible) =
             self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
 
@@ -354,7 +353,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::Call(fun, ref args) => {
-                if self.typeck_results().is_method_call(expr) {
+                if self.typeck_results.is_method_call(expr) {
                     // The callee is something implementing Fn, FnMut, or FnOnce.
                     // Find the actual method implementation being called and
                     // build the appropriate UFCS call expression with the
@@ -364,7 +363,7 @@ impl<'tcx> Cx<'tcx> {
 
                     let method = self.method_callee(expr, fun.span, None);
 
-                    let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e));
+                    let arg_tys = args.iter().map(|e| self.typeck_results.expr_ty_adjusted(e));
                     let tupled_args = Expr {
                         ty: Ty::new_tup_from_iter(tcx, arg_tys),
                         temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
@@ -380,7 +379,7 @@ impl<'tcx> Cx<'tcx> {
                         from_hir_call: true,
                         fn_span: expr.span,
                     }
-                } else if let ty::FnDef(def_id, _) = self.typeck_results().expr_ty(fun).kind()
+                } else if let ty::FnDef(def_id, _) = self.typeck_results.expr_ty(fun).kind()
                     && let Some(intrinsic) = self.tcx.intrinsic(def_id)
                     && intrinsic.name == sym::box_new
                 {
@@ -413,7 +412,7 @@ impl<'tcx> Cx<'tcx> {
                             },
                             hir::QPath::TypeRelative(_ty, _) => {
                                 if let Some((DefKind::Ctor(_, CtorKind::Fn), ctor_id)) =
-                                    self.typeck_results().type_dependent_def(fun.hir_id)
+                                    self.typeck_results.type_dependent_def(fun.hir_id)
                                 {
                                     Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
                                 } else {
@@ -426,8 +425,8 @@ impl<'tcx> Cx<'tcx> {
                         None
                     };
                     if let Some((adt_def, index)) = adt_data {
-                        let node_args = self.typeck_results().node_args(fun.hir_id);
-                        let user_provided_types = self.typeck_results().user_provided_types();
+                        let node_args = self.typeck_results.node_args(fun.hir_id);
+                        let user_provided_types = self.typeck_results.user_provided_types();
                         let user_ty =
                             user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
                                 if let ty::UserTypeKind::TypeOf(ref mut did, _) =
@@ -457,7 +456,7 @@ impl<'tcx> Cx<'tcx> {
                         }))
                     } else {
                         ExprKind::Call {
-                            ty: self.typeck_results().node_type(fun.hir_id),
+                            ty: self.typeck_results.node_type(fun.hir_id),
                             fun: self.mirror_expr(fun),
                             args: self.mirror_exprs(args),
                             from_hir_call: true,
@@ -482,7 +481,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::AssignOp(op, lhs, rhs) => {
-                if self.typeck_results().is_method_call(expr) {
+                if self.typeck_results.is_method_call(expr) {
                     let lhs = self.mirror_expr(lhs);
                     let rhs = self.mirror_expr(rhs);
                     self.overloaded_operator(expr, Box::new([lhs, rhs]))
@@ -498,7 +497,7 @@ impl<'tcx> Cx<'tcx> {
             hir::ExprKind::Lit(lit) => ExprKind::Literal { lit, neg: false },
 
             hir::ExprKind::Binary(op, lhs, rhs) => {
-                if self.typeck_results().is_method_call(expr) {
+                if self.typeck_results.is_method_call(expr) {
                     let lhs = self.mirror_expr(lhs);
                     let rhs = self.mirror_expr(rhs);
                     self.overloaded_operator(expr, Box::new([lhs, rhs]))
@@ -527,7 +526,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::Index(lhs, index, brackets_span) => {
-                if self.typeck_results().is_method_call(expr) {
+                if self.typeck_results.is_method_call(expr) {
                     let lhs = self.mirror_expr(lhs);
                     let index = self.mirror_expr(index);
                     self.overloaded_place(
@@ -543,7 +542,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::Unary(hir::UnOp::Deref, arg) => {
-                if self.typeck_results().is_method_call(expr) {
+                if self.typeck_results.is_method_call(expr) {
                     let arg = self.mirror_expr(arg);
                     self.overloaded_place(expr, expr_ty, None, Box::new([arg]), expr.span)
                 } else {
@@ -552,7 +551,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::Unary(hir::UnOp::Not, arg) => {
-                if self.typeck_results().is_method_call(expr) {
+                if self.typeck_results.is_method_call(expr) {
                     let arg = self.mirror_expr(arg);
                     self.overloaded_operator(expr, Box::new([arg]))
                 } else {
@@ -561,7 +560,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::Unary(hir::UnOp::Neg, arg) => {
-                if self.typeck_results().is_method_call(expr) {
+                if self.typeck_results.is_method_call(expr) {
                     let arg = self.mirror_expr(arg);
                     self.overloaded_operator(expr, Box::new([arg]))
                 } else if let hir::ExprKind::Lit(lit) = arg.kind {
@@ -574,7 +573,7 @@ impl<'tcx> Cx<'tcx> {
             hir::ExprKind::Struct(qpath, fields, ref base) => match expr_ty.kind() {
                 ty::Adt(adt, args) => match adt.adt_kind() {
                     AdtKind::Struct | AdtKind::Union => {
-                        let user_provided_types = self.typeck_results().user_provided_types();
+                        let user_provided_types = self.typeck_results.user_provided_types();
                         let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
                         debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
                         ExprKind::Adt(Box::new(AdtExpr {
@@ -586,15 +585,14 @@ impl<'tcx> Cx<'tcx> {
                             base: match base {
                                 hir::StructTailExpr::Base(base) => AdtExprBase::Base(FruInfo {
                                     base: self.mirror_expr(base),
-                                    field_types: self.typeck_results().fru_field_types()
-                                        [expr.hir_id]
+                                    field_types: self.typeck_results.fru_field_types()[expr.hir_id]
                                         .iter()
                                         .copied()
                                         .collect(),
                                 }),
                                 hir::StructTailExpr::DefaultFields(_) => {
                                     AdtExprBase::DefaultFields(
-                                        self.typeck_results().fru_field_types()[expr.hir_id]
+                                        self.typeck_results.fru_field_types()[expr.hir_id]
                                             .iter()
                                             .copied()
                                             .collect(),
@@ -605,7 +603,7 @@ impl<'tcx> Cx<'tcx> {
                         }))
                     }
                     AdtKind::Enum => {
-                        let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
+                        let res = self.typeck_results.qpath_res(qpath, expr.hir_id);
                         match res {
                             Res::Def(DefKind::Variant, variant_id) => {
                                 assert!(matches!(
@@ -615,8 +613,7 @@ impl<'tcx> Cx<'tcx> {
                                 ));
 
                                 let index = adt.variant_index_with_id(variant_id);
-                                let user_provided_types =
-                                    self.typeck_results().user_provided_types();
+                                let user_provided_types = self.typeck_results.user_provided_types();
                                 let user_ty =
                                     user_provided_types.get(expr.hir_id).copied().map(Box::new);
                                 debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
@@ -629,8 +626,7 @@ impl<'tcx> Cx<'tcx> {
                                     base: match base {
                                         hir::StructTailExpr::DefaultFields(_) => {
                                             AdtExprBase::DefaultFields(
-                                                self.typeck_results().fru_field_types()
-                                                    [expr.hir_id]
+                                                self.typeck_results.fru_field_types()[expr.hir_id]
                                                     .iter()
                                                     .copied()
                                                     .collect(),
@@ -655,7 +651,7 @@ impl<'tcx> Cx<'tcx> {
             },
 
             hir::ExprKind::Closure { .. } => {
-                let closure_ty = self.typeck_results().expr_ty(expr);
+                let closure_ty = self.typeck_results.expr_ty(expr);
                 let (def_id, args, movability) = match *closure_ty.kind() {
                     ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None),
                     ty::Coroutine(def_id, args) => {
@@ -703,7 +699,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::Path(ref qpath) => {
-                let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
+                let res = self.typeck_results.qpath_res(qpath, expr.hir_id);
                 self.convert_path_expr(expr, res)
             }
 
@@ -772,7 +768,7 @@ impl<'tcx> Cx<'tcx> {
             }
 
             hir::ExprKind::ConstBlock(ref anon_const) => {
-                let ty = self.typeck_results().node_type(anon_const.hir_id);
+                let ty = self.typeck_results.node_type(anon_const.hir_id);
                 let did = anon_const.def_id.to_def_id();
                 let typeck_root_def_id = tcx.typeck_root_def_id(did);
                 let parent_args =
@@ -783,7 +779,7 @@ impl<'tcx> Cx<'tcx> {
             }
             // Now comes the rote stuff:
             hir::ExprKind::Repeat(v, _) => {
-                let ty = self.typeck_results().expr_ty(expr);
+                let ty = self.typeck_results.expr_ty(expr);
                 let ty::Array(_, count) = ty.kind() else {
                     span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty);
                 };
@@ -837,7 +833,7 @@ impl<'tcx> Cx<'tcx> {
                 match_source,
             },
             hir::ExprKind::Loop(body, ..) => {
-                let block_ty = self.typeck_results().node_type(body.hir_id);
+                let block_ty = self.typeck_results.node_type(body.hir_id);
                 let (temp_lifetime, backwards_incompatible) = self
                     .rvalue_scopes
                     .temporary_scope(self.region_scope_tree, body.hir_id.local_id);
@@ -957,7 +953,7 @@ impl<'tcx> Cx<'tcx> {
             | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
             | Res::Def(DefKind::Const, _)
             | Res::Def(DefKind::AssocConst, _) => {
-                self.typeck_results().user_provided_types().get(hir_id).copied().map(Box::new)
+                self.typeck_results.user_provided_types().get(hir_id).copied().map(Box::new)
             }
 
             // A unit struct/variant which is used as a value (e.g.,
@@ -989,17 +985,13 @@ impl<'tcx> Cx<'tcx> {
             Some(fn_def) => (fn_def, None),
             None => {
                 let (kind, def_id) =
-                    self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| {
+                    self.typeck_results.type_dependent_def(expr.hir_id).unwrap_or_else(|| {
                         span_bug!(expr.span, "no type-dependent def for method callee")
                     });
                 let user_ty = self.user_args_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
                 debug!("method_callee: user_ty={:?}", user_ty);
                 (
-                    Ty::new_fn_def(
-                        self.tcx(),
-                        def_id,
-                        self.typeck_results().node_args(expr.hir_id),
-                    ),
+                    Ty::new_fn_def(self.tcx, def_id, self.typeck_results.node_args(expr.hir_id)),
                     user_ty,
                 )
             }
@@ -1025,7 +1017,7 @@ impl<'tcx> Cx<'tcx> {
     }
 
     fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
-        let args = self.typeck_results().node_args(expr.hir_id);
+        let args = self.typeck_results.node_args(expr.hir_id);
         match res {
             // A regular function, constructor function or a constant.
             Res::Def(DefKind::Fn, _)
@@ -1060,7 +1052,7 @@ impl<'tcx> Cx<'tcx> {
                 let user_provided_types = self.typeck_results.user_provided_types();
                 let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new);
                 debug!("convert_path_expr: user_ty={:?}", user_ty);
-                let ty = self.typeck_results().node_type(expr.hir_id);
+                let ty = self.typeck_results.node_type(expr.hir_id);
                 match ty.kind() {
                     // A unit struct/variant which is used as a value.
                     // We return a completely different ExprKind here to account for this special case.
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index a98c2bb61f666..9d114e6755931 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -16,15 +16,15 @@ use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
 use tracing::instrument;
 
 use crate::thir::pattern::pat_from_hir;
-use crate::thir::util::UserAnnotatedTyHelpers;
 
+/// Query implementation for [`TyCtxt::thir_body`].
 pub(crate) fn thir_body(
     tcx: TyCtxt<'_>,
     owner_def: LocalDefId,
 ) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> {
     let hir = tcx.hir();
     let body = hir.body_owned_by(owner_def);
-    let mut cx = Cx::new(tcx, owner_def);
+    let mut cx = ThirBuildCx::new(tcx, owner_def);
     if let Some(reported) = cx.typeck_results.tainted_by_errors {
         return Err(reported);
     }
@@ -52,8 +52,10 @@ pub(crate) fn thir_body(
     Ok((tcx.alloc_steal_thir(cx.thir), expr))
 }
 
-struct Cx<'tcx> {
+/// Context for lowering HIR to THIR for a single function body (or other kind of body).
+struct ThirBuildCx<'tcx> {
     tcx: TyCtxt<'tcx>,
+    /// The THIR data that this context is building.
     thir: Thir<'tcx>,
 
     typing_env: ty::TypingEnv<'tcx>,
@@ -69,8 +71,8 @@ struct Cx<'tcx> {
     body_owner: DefId,
 }
 
-impl<'tcx> Cx<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Cx<'tcx> {
+impl<'tcx> ThirBuildCx<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
         let typeck_results = tcx.typeck(def);
         let hir = tcx.hir();
         let hir_id = tcx.local_def_id_to_hir_id(def);
@@ -94,7 +96,7 @@ impl<'tcx> Cx<'tcx> {
             BodyTy::Const(typeck_results.node_type(hir_id))
         };
 
-        Cx {
+        Self {
             tcx,
             thir: Thir::new(body_type),
             // FIXME(#132279): We're in a body, we should use a typing
@@ -113,7 +115,7 @@ impl<'tcx> Cx<'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
-        pat_from_hir(self.tcx, self.typing_env, self.typeck_results(), p)
+        pat_from_hir(self.tcx, self.typing_env, self.typeck_results, p)
     }
 
     fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {
@@ -197,15 +199,12 @@ impl<'tcx> Cx<'tcx> {
             Param { pat: Some(pat), ty, ty_span, self_kind, hir_id: Some(param.hir_id) }
         })
     }
-}
-
-impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
 
-    fn typeck_results(&self) -> &ty::TypeckResults<'tcx> {
-        self.typeck_results
+    fn user_args_applied_to_ty_of_hir_id(
+        &self,
+        hir_id: HirId,
+    ) -> Option<ty::CanonicalUserType<'tcx>> {
+        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
     }
 }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 0aa61152330a7..8ecdbecf1651a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -27,7 +27,6 @@ use tracing::{debug, instrument};
 pub(crate) use self::check_match::check_match;
 use crate::errors::*;
 use crate::fluent_generated as fluent;
-use crate::thir::util::UserAnnotatedTyHelpers;
 
 struct PatCtxt<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -540,16 +539,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             _ => {
                 let e = match res {
                     Res::Def(DefKind::ConstParam, def_id) => {
-                        self.tcx.dcx().emit_err(ConstParamInPattern {
-                            span,
-                            const_span: self.tcx().def_span(def_id),
-                        })
+                        let const_span = self.tcx.def_span(def_id);
+                        self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span })
                     }
                     Res::Def(DefKind::Static { .. }, def_id) => {
-                        self.tcx.dcx().emit_err(StaticInPattern {
-                            span,
-                            static_span: self.tcx().def_span(def_id),
-                        })
+                        let static_span = self.tcx.def_span(def_id);
+                        self.tcx.dcx().emit_err(StaticInPattern { span, static_span })
                     }
                     _ => self.tcx.dcx().emit_err(NonConstPath { span }),
                 };
@@ -573,6 +568,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         kind
     }
 
+    fn user_args_applied_to_ty_of_hir_id(
+        &self,
+        hir_id: hir::HirId,
+    ) -> Option<ty::CanonicalUserType<'tcx>> {
+        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
+    }
+
     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
     /// it to `const_to_pat`. Any other path (like enum variants without fields)
     /// is converted to the corresponding pattern via `lower_variant_or_leaf`.
@@ -603,12 +605,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             return pattern;
         }
 
-        let user_provided_types = self.typeck_results().user_provided_types();
+        let user_provided_types = self.typeck_results.user_provided_types();
         if let Some(&user_ty) = user_provided_types.get(id) {
             let annotation = CanonicalUserTypeAnnotation {
                 user_ty: Box::new(user_ty),
                 span,
-                inferred_ty: self.typeck_results().node_type(id),
+                inferred_ty: self.typeck_results.node_type(id),
             };
             Box::new(Pat {
                 span,
@@ -672,13 +674,3 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind
     }
 }
-
-impl<'tcx> UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn typeck_results(&self) -> &ty::TypeckResults<'tcx> {
-        self.typeck_results
-    }
-}
diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs
index ed7c7e4099304..4dff093afd0d9 100644
--- a/compiler/rustc_mir_build/src/thir/util.rs
+++ b/compiler/rustc_mir_build/src/thir/util.rs
@@ -1,33 +1,27 @@
 use rustc_hir as hir;
 use rustc_middle::bug;
-use rustc_middle::ty::{self, CanonicalUserType, TyCtxt};
+use rustc_middle::ty::{self, CanonicalUserType};
 use tracing::debug;
 
-pub(crate) trait UserAnnotatedTyHelpers<'tcx> {
-    fn tcx(&self) -> TyCtxt<'tcx>;
-
-    fn typeck_results(&self) -> &ty::TypeckResults<'tcx>;
-
-    /// Looks up the type associated with this hir-id and applies the
-    /// user-given generic parameters; the hir-id must map to a suitable
-    /// type.
-    fn user_args_applied_to_ty_of_hir_id(
-        &self,
-        hir_id: hir::HirId,
-    ) -> Option<CanonicalUserType<'tcx>> {
-        let user_provided_types = self.typeck_results().user_provided_types();
-        let mut user_ty = *user_provided_types.get(hir_id)?;
-        debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty);
-        let ty = self.typeck_results().node_type(hir_id);
-        match ty.kind() {
-            ty::Adt(adt_def, ..) => {
-                if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind {
-                    *did = adt_def.did();
-                }
-                Some(user_ty)
+/// Looks up the type associated with this hir-id and applies the
+/// user-given generic parameters; the hir-id must map to a suitable
+/// type.
+pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>(
+    typeck_results: &ty::TypeckResults<'tcx>,
+    hir_id: hir::HirId,
+) -> Option<CanonicalUserType<'tcx>> {
+    let user_provided_types = typeck_results.user_provided_types();
+    let mut user_ty = *user_provided_types.get(hir_id)?;
+    debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty);
+    let ty = typeck_results.node_type(hir_id);
+    match ty.kind() {
+        ty::Adt(adt_def, ..) => {
+            if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind {
+                *did = adt_def.did();
             }
-            ty::FnDef(..) => Some(user_ty),
-            _ => bug!("ty: {:?} should not have user provided type {:?} recorded ", ty, user_ty),
+            Some(user_ty)
         }
+        ty::FnDef(..) => Some(user_ty),
+        _ => bug!("ty: {:?} should not have user provided type {:?} recorded ", ty, user_ty),
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 6e00e427a46c7..b6c259aa4e0ab 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -417,7 +417,11 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
             | Rvalue::Discriminant(..)
             | Rvalue::Len(..)
             | Rvalue::NullaryOp(
-                NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::UbChecks,
+                NullOp::SizeOf
+                | NullOp::AlignOf
+                | NullOp::OffsetOf(..)
+                | NullOp::UbChecks
+                | NullOp::ContractChecks,
                 _,
             ) => {}
         }
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index c261e25100d38..d2ffd26f0a06d 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -545,6 +545,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                         .offset_of_subfield(self.typing_env(), layout, fields.iter())
                         .bytes(),
                     NullOp::UbChecks => return None,
+                    NullOp::ContractChecks => return None,
                 };
                 let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
                 let imm = ImmTy::from_uint(val, usize_layout);
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 2864cc0b9fe0c..e43254ba089e5 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -629,6 +629,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                         .offset_of_subfield(self.typing_env, op_layout, fields.iter())
                         .bytes(),
                     NullOp::UbChecks => return None,
+                    NullOp::ContractChecks => return None,
                 };
                 ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into()
             }
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 9a9f66ed4fd7a..9c21bcfc0d26a 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -34,6 +34,17 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
                         });
                         terminator.kind = TerminatorKind::Goto { target };
                     }
+                    sym::contract_checks => {
+                        let target = target.unwrap();
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::NullaryOp(NullOp::ContractChecks, tcx.types.bool),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::forget => {
                         let target = target.unwrap();
                         block.statements.push(Statement {
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 9101c9bfc9aeb..4dbbcae1756b7 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -457,6 +457,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                 NullOp::AlignOf => {}
                 NullOp::OffsetOf(_) => {}
                 NullOp::UbChecks => {}
+                NullOp::ContractChecks => {}
             },
 
             Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index e282eaf761c10..b7a3770fc6b1d 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1379,7 +1379,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             Rvalue::Repeat(_, _)
             | Rvalue::ThreadLocalRef(_)
             | Rvalue::RawPtr(_, _)
-            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::UbChecks, _)
+            | Rvalue::NullaryOp(
+                NullOp::SizeOf | NullOp::AlignOf | NullOp::UbChecks | NullOp::ContractChecks,
+                _,
+            )
             | Rvalue::Discriminant(_) => {}
 
             Rvalue::WrapUnsafeBinder(op, ty) => {
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index b1b84b0b7011e..86816819be275 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -4,7 +4,7 @@ use rustc_ast::{
     WhereClause, token,
 };
 use rustc_errors::{Applicability, PResult};
-use rustc_span::{Ident, Span, kw};
+use rustc_span::{Ident, Span, kw, sym};
 use thin_vec::ThinVec;
 
 use super::{ForceCollect, Parser, Trailing, UsePreAttrPos};
@@ -297,6 +297,42 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Parses an experimental fn contract
+    /// (`contract_requires(WWW) contract_ensures(ZZZ)`)
+    pub(super) fn parse_contract(
+        &mut self,
+    ) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> {
+        let gate = |span| {
+            if self.psess.contract_attribute_spans.contains(span) {
+                // span was generated via a builtin contracts attribute, so gate as end-user visible
+                self.psess.gated_spans.gate(sym::contracts, span);
+            } else {
+                // span was not generated via a builtin contracts attribute, so gate as internal machinery
+                self.psess.gated_spans.gate(sym::contracts_internals, span);
+            }
+        };
+
+        let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
+            let precond = self.parse_expr()?;
+            gate(precond.span);
+            Some(precond)
+        } else {
+            None
+        };
+        let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
+            let postcond = self.parse_expr()?;
+            gate(postcond.span);
+            Some(postcond)
+        } else {
+            None
+        };
+        if requires.is_none() && ensures.is_none() {
+            Ok(None)
+        } else {
+            Ok(Some(rustc_ast::ptr::P(ast::FnContract { requires, ensures })))
+        }
+    }
+
     /// Parses an optional where-clause.
     ///
     /// ```ignore (only-for-syntax-highlight)
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index f3e56be9f6e8b..dbdc31f06a29d 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -213,9 +213,12 @@ impl<'a> Parser<'a> {
             self.parse_use_item()?
         } else if self.check_fn_front_matter(check_pub, case) {
             // FUNCTION ITEM
-            let (ident, sig, generics, body) =
+            let (ident, sig, generics, contract, body) =
                 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
-            (ident, ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, body })))
+            (
+                ident,
+                ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, contract, body })),
+            )
         } else if self.eat_keyword(exp!(Extern)) {
             if self.eat_keyword(exp!(Crate)) {
                 // EXTERN CRATE
@@ -2372,7 +2375,7 @@ impl<'a> Parser<'a> {
         sig_lo: Span,
         vis: &Visibility,
         case: Case,
-    ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
+    ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<FnContract>>, Option<P<Block>>)> {
         let fn_span = self.token.span;
         let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
         let ident = self.parse_ident()?; // `foo`
@@ -2398,6 +2401,8 @@ impl<'a> Parser<'a> {
         // inside `parse_fn_body()`.
         let fn_params_end = self.prev_token.span.shrink_to_hi();
 
+        let contract = self.parse_contract()?;
+
         generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
 
         // `fn_params_end` is needed only when it's followed by a where clause.
@@ -2409,7 +2414,7 @@ impl<'a> Parser<'a> {
         let body =
             self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
         let fn_sig_span = sig_lo.to(sig_hi);
-        Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
+        Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
     }
 
     /// Provide diagnostics when function body is not found
diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs
index 73f3ac001c8ae..40631d9154d37 100644
--- a/compiler/rustc_parse/src/parser/token_type.rs
+++ b/compiler/rustc_parse/src/parser/token_type.rs
@@ -83,6 +83,8 @@ pub enum TokenType {
     KwCatch,
     KwConst,
     KwContinue,
+    KwContractEnsures,
+    KwContractRequires,
     KwCrate,
     KwDefault,
     KwDyn,
@@ -217,6 +219,8 @@ impl TokenType {
             KwCatch,
             KwConst,
             KwContinue,
+            KwContractEnsures,
+            KwContractRequires,
             KwCrate,
             KwDefault,
             KwDyn,
@@ -289,6 +293,8 @@ impl TokenType {
             TokenType::KwCatch => Some(kw::Catch),
             TokenType::KwConst => Some(kw::Const),
             TokenType::KwContinue => Some(kw::Continue),
+            TokenType::KwContractEnsures => Some(kw::ContractEnsures),
+            TokenType::KwContractRequires => Some(kw::ContractRequires),
             TokenType::KwCrate => Some(kw::Crate),
             TokenType::KwDefault => Some(kw::Default),
             TokenType::KwDyn => Some(kw::Dyn),
@@ -519,6 +525,8 @@ macro_rules! exp {
     (Catch)          => { exp!(@kw, Catch,      KwCatch) };
     (Const)          => { exp!(@kw, Const,      KwConst) };
     (Continue)       => { exp!(@kw, Continue,   KwContinue) };
+    (ContractEnsures)  => { exp!(@kw, ContractEnsures, KwContractEnsures) };
+    (ContractRequires) => { exp!(@kw, ContractRequires, KwContractRequires) };
     (Crate)          => { exp!(@kw, Crate,      KwCrate) };
     (Default)        => { exp!(@kw, Default,    KwDefault) };
     (Dyn)            => { exp!(@kw, Dyn,        KwDyn) };
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 16c0a345f8791..db607dbb41963 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -174,10 +174,13 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                 _ctxt,
                 _ident,
                 _vis,
-                Fn { sig: FnSig { header, decl, span: _ }, generics, body, .. },
+                Fn { sig: FnSig { header, decl, span: _ }, generics, contract, body, .. },
             ) if let Some(coroutine_kind) = header.coroutine_kind => {
                 self.visit_fn_header(header);
                 self.visit_generics(generics);
+                if let Some(contract) = contract {
+                    self.visit_contract(contract);
+                }
 
                 // For async functions, we need to create their inner defs inside of a
                 // closure to match their desugared representation. Besides that,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 4842cbd556c37..e37e7e98ee7aa 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1019,7 +1019,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
             // Create a label rib for the function.
             this.with_label_rib(RibKind::FnOrCoroutine, |this| {
                 match fn_kind {
-                    FnKind::Fn(_, _, _, Fn { sig, generics, body, .. }) => {
+                    FnKind::Fn(_, _, _, Fn { sig, generics, contract, body, .. }) => {
                         this.visit_generics(generics);
 
                         let declaration = &sig.decl;
@@ -1046,6 +1046,10 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                             },
                         );
 
+                        if let Some(contract) = contract {
+                            this.visit_contract(contract);
+                        }
+
                         if let Some(body) = body {
                             // Ignore errors in function bodies if this is rustdoc
                             // Be sure not to set this until the function signature has been resolved.
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index d586f913335e0..52920e0372e2b 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -119,6 +119,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
             (sym::overflow_checks, None) => disallow(cfg, "-C overflow-checks"),
             (sym::debug_assertions, None) => disallow(cfg, "-C debug-assertions"),
             (sym::ub_checks, None) => disallow(cfg, "-Z ub-checks"),
+            (sym::contract_checks, None) => disallow(cfg, "-Z contract-checks"),
             (sym::sanitize, None | Some(_)) => disallow(cfg, "-Z sanitizer"),
             (
                 sym::sanitizer_cfi_generalize_pointers | sym::sanitizer_cfi_normalize_integers,
@@ -300,6 +301,11 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
     if sess.is_nightly_build() && sess.opts.unstable_opts.emscripten_wasm_eh {
         ins_none!(sym::emscripten_wasm_eh);
     }
+
+    if sess.contract_checks() {
+        ins_none!(sym::contract_checks);
+    }
+
     ret
 }
 
@@ -464,6 +470,7 @@ impl CheckCfg {
         ins!(sym::target_thread_local, no_values);
 
         ins!(sym::ub_checks, no_values);
+        ins!(sym::contract_checks, no_values);
 
         ins!(sym::unix, no_values);
         ins!(sym::windows, no_values);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 4ed5499d32c6d..35819f896c5bd 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -2114,6 +2114,8 @@ options! {
         "the backend to use"),
     combine_cgu: bool = (false, parse_bool, [TRACKED],
         "combine CGUs into a single one"),
+    contract_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
+        "emit runtime checks for contract pre- and post-conditions (default: no)"),
     coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED],
         "control details of coverage instrumentation"),
     crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 81ae06602cdb9..abfd3efc6117c 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -207,6 +207,10 @@ pub struct ParseSess {
     pub config: Cfg,
     pub check_config: CheckCfg,
     pub edition: Edition,
+    /// Places where contract attributes were expanded into unstable AST forms.
+    /// This is used to allowlist those spans (so that we only check them against the feature
+    /// gate for the externally visible interface, and not internal implmentation machinery).
+    pub contract_attribute_spans: AppendOnlyVec<Span>,
     /// Places where raw identifiers were used. This is used to avoid complaining about idents
     /// clashing with keywords in new editions.
     pub raw_identifier_spans: AppendOnlyVec<Span>,
@@ -255,6 +259,7 @@ impl ParseSess {
             config: Cfg::default(),
             check_config: CheckCfg::default(),
             edition: ExpnId::root().expn_data().edition,
+            contract_attribute_spans: Default::default(),
             raw_identifier_spans: Default::default(),
             bad_unicode_identifiers: Lock::new(Default::default()),
             source_map,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 2b79081a26e72..c9bb42bdfa1ec 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -709,6 +709,10 @@ impl Session {
         self.opts.unstable_opts.ub_checks.unwrap_or(self.opts.debug_assertions)
     }
 
+    pub fn contract_checks(&self) -> bool {
+        self.opts.unstable_opts.contract_checks.unwrap_or(false)
+    }
+
     pub fn relocation_model(&self) -> RelocModel {
         self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model)
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 4a0420cc60311..bdd6e16a7c171 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -291,6 +291,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
                 indices.iter().map(|idx| idx.stable(tables)).collect(),
             ),
             UbChecks => stable_mir::mir::NullOp::UbChecks,
+            ContractChecks => stable_mir::mir::NullOp::ContractChecks,
         }
     }
 }
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index a5826137181db..dbbbb5077cb5c 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1163,6 +1163,8 @@ pub enum DesugaringKind {
     WhileLoop,
     /// `async Fn()` bound modifier
     BoundModifier,
+    /// Calls to contract checks (`#[requires]` to precond, `#[ensures]` to postcond)
+    Contract,
 }
 
 impl DesugaringKind {
@@ -1179,6 +1181,7 @@ impl DesugaringKind {
             DesugaringKind::ForLoop => "`for` loop",
             DesugaringKind::WhileLoop => "`while` loop",
             DesugaringKind::BoundModifier => "trait bound modifier",
+            DesugaringKind::Contract => "contract check",
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 382b12638f43f..e0cb68323d00b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -118,6 +118,8 @@ symbols! {
         MacroRules:         "macro_rules",
         Raw:                "raw",
         Reuse:              "reuse",
+        ContractEnsures:  "contract_ensures",
+        ContractRequires: "contract_requires",
         Safe:               "safe",
         Union:              "union",
         Yeet:               "yeet",
@@ -566,6 +568,7 @@ symbols! {
         cfg_attr,
         cfg_attr_multi,
         cfg_boolean_literals,
+        cfg_contract_checks,
         cfg_doctest,
         cfg_emscripten_wasm_eh,
         cfg_eval,
@@ -675,6 +678,14 @@ symbols! {
         const_ty_placeholder: "<const_ty>",
         constant,
         constructor,
+        contract_build_check_ensures,
+        contract_check_ensures,
+        contract_check_requires,
+        contract_checks,
+        contracts,
+        contracts_ensures,
+        contracts_internals,
+        contracts_requires,
         convert_identity,
         copy,
         copy_closures,
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index eec6cd8d49ba3..a6406e9db8e35 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -608,7 +608,8 @@ impl Rvalue {
             Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
                 Ok(Ty::usize_ty())
             }
-            Rvalue::NullaryOp(NullOp::UbChecks, _) => Ok(Ty::bool_ty()),
+            Rvalue::NullaryOp(NullOp::ContractChecks, _)
+            | Rvalue::NullaryOp(NullOp::UbChecks, _) => Ok(Ty::bool_ty()),
             Rvalue::Aggregate(ak, ops) => match *ak {
                 AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64),
                 AggregateKind::Tuple => Ok(Ty::new_tuple(
@@ -1007,6 +1008,8 @@ pub enum NullOp {
     OffsetOf(Vec<(VariantIdx, FieldIdx)>),
     /// cfg!(ub_checks), but at codegen time
     UbChecks,
+    /// cfg!(contract_checks), but at codegen time
+    ContractChecks,
 }
 
 impl Operand {
diff --git a/library/core/src/contracts.rs b/library/core/src/contracts.rs
new file mode 100644
index 0000000000000..c769e219e4d49
--- /dev/null
+++ b/library/core/src/contracts.rs
@@ -0,0 +1,21 @@
+//! Unstable module containing the unstable contracts lang items and attribute macros.
+#![cfg(not(bootstrap))]
+
+pub use crate::macros::builtin::{contracts_ensures as ensures, contracts_requires as requires};
+
+/// Emitted by rustc as a desugaring of `#[ensures(PRED)] fn foo() -> R { ... [return R;] ... }`
+/// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }`
+/// (including the implicit return of the tail expression, if any).
+#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
+#[lang = "contract_build_check_ensures"]
+#[track_caller]
+pub fn build_check_ensures<Ret, C>(cond: C) -> impl (Fn(Ret) -> Ret) + Copy
+where
+    C: for<'a> Fn(&'a Ret) -> bool + Copy + 'static,
+{
+    #[track_caller]
+    move |ret| {
+        crate::intrinsics::contract_check_ensures(&ret, cond);
+        ret
+    }
+}
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 1862be0e86c5d..665b05b12ec07 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -1228,6 +1228,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
 /// assert_eq!(format!("{:?}", wrapped), "'a'");
 /// ```
 #[unstable(feature = "debug_closure_helpers", issue = "117729")]
+#[must_use = "returns a type implementing Debug and Display, which do not have any effects unless they are used"]
 pub fn from_fn<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result>(f: F) -> FromFn<F> {
     FromFn(f)
 }
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index bf07632d9928b..1e4dc12f9b617 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -4044,6 +4044,52 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize)
     // Runtime NOP
 }
 
+/// Returns whether we should perform contract-checking at runtime.
+///
+/// This is meant to be similar to the ub_checks intrinsic, in terms
+/// of not prematurely commiting at compile-time to whether contract
+/// checking is turned on, so that we can specify contracts in libstd
+/// and let an end user opt into turning them on.
+#[cfg(not(bootstrap))]
+#[rustc_const_unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
+#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
+#[inline(always)]
+#[rustc_intrinsic]
+pub const fn contract_checks() -> bool {
+    // FIXME: should this be `false` or `cfg!(contract_checks)`?
+
+    // cfg!(contract_checks)
+    false
+}
+
+/// Check if the pre-condition `cond` has been met.
+///
+/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
+/// returns false.
+#[cfg(not(bootstrap))]
+#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
+#[lang = "contract_check_requires"]
+#[rustc_intrinsic]
+pub fn contract_check_requires<C: Fn() -> bool>(cond: C) {
+    if contract_checks() && !cond() {
+        // Emit no unwind panic in case this was a safety requirement.
+        crate::panicking::panic_nounwind("failed requires check");
+    }
+}
+
+/// Check if the post-condition `cond` has been met.
+///
+/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
+/// returns false.
+#[cfg(not(bootstrap))]
+#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
+#[rustc_intrinsic]
+pub fn contract_check_ensures<'a, Ret, C: Fn(&'a Ret) -> bool>(ret: &'a Ret, cond: C) {
+    if contract_checks() && !cond(ret) {
+        crate::panicking::panic_nounwind("failed ensures check");
+    }
+}
+
 /// The intrinsic will return the size stored in that vtable.
 ///
 /// # Safety
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index c18e0405f7293..de8e85f7b36ed 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -113,6 +113,7 @@
 #![feature(bigint_helper_methods)]
 #![feature(bstr)]
 #![feature(bstr_internals)]
+#![feature(closure_track_caller)]
 #![feature(const_carrying_mul_add)]
 #![feature(const_eval_select)]
 #![feature(core_intrinsics)]
@@ -246,6 +247,10 @@ pub mod autodiff {
     pub use crate::macros::builtin::autodiff;
 }
 
+#[cfg(not(bootstrap))]
+#[unstable(feature = "contracts", issue = "128044")]
+pub mod contracts;
+
 #[unstable(feature = "cfg_match", issue = "115585")]
 pub use crate::macros::cfg_match;
 
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 3669051ce82d3..4c6fd196bd31c 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1777,6 +1777,32 @@ pub(crate) mod builtin {
         /* compiler built-in */
     }
 
+    /// Attribute macro applied to a function to give it a post-condition.
+    ///
+    /// The attribute carries an argument token-tree which is
+    /// eventually parsed as a unary closure expression that is
+    /// invoked on a reference to the return value.
+    #[cfg(not(bootstrap))]
+    #[unstable(feature = "contracts", issue = "128044")]
+    #[allow_internal_unstable(contracts_internals)]
+    #[rustc_builtin_macro]
+    pub macro contracts_ensures($item:item) {
+        /* compiler built-in */
+    }
+
+    /// Attribute macro applied to a function to give it a precondition.
+    ///
+    /// The attribute carries an argument token-tree which is
+    /// eventually parsed as an boolean expression with access to the
+    /// function's formal parameters
+    #[cfg(not(bootstrap))]
+    #[unstable(feature = "contracts", issue = "128044")]
+    #[allow_internal_unstable(contracts_internals)]
+    #[rustc_builtin_macro]
+    pub macro contracts_requires($item:item) {
+        /* compiler built-in */
+    }
+
     /// Attribute macro applied to a function to register it as a handler for allocation failure.
     ///
     /// See also [`std::alloc::handle_alloc_error`](../../../std/alloc/fn.handle_alloc_error.html).
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 5fcf7eda8df79..441674936c666 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -11,12 +11,12 @@ use std::str::FromStr;
 use std::{env, process};
 
 use bootstrap::{
-    Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, find_recent_config_change_ids,
+    Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, debug, find_recent_config_change_ids,
     human_readable_changes, t,
 };
 use build_helper::ci::CiEnv;
 #[cfg(feature = "tracing")]
-use tracing::{debug, instrument};
+use tracing::instrument;
 
 #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))]
 fn main() {
@@ -29,10 +29,8 @@ fn main() {
         return;
     }
 
-    #[cfg(feature = "tracing")]
     debug!("parsing flags");
     let flags = Flags::parse(&args);
-    #[cfg(feature = "tracing")]
     debug!("parsing config based on flags");
     let config = Config::parse(flags);
 
@@ -95,7 +93,6 @@ fn main() {
     let dump_bootstrap_shims = config.dump_bootstrap_shims;
     let out_dir = config.out.clone();
 
-    #[cfg(feature = "tracing")]
     debug!("creating new build based on config");
     Build::new(config).build();
 
@@ -207,8 +204,9 @@ fn check_version(config: &Config) -> Option<String> {
 // Due to the conditional compilation via the `tracing` cargo feature, this means that `tracing`
 // usages in bootstrap need to be also gated behind the `tracing` feature:
 //
-// - `tracing` macros (like `trace!`) and anything from `tracing`, `tracing_subscriber` and
-//   `tracing-tree` will need to be gated by `#[cfg(feature = "tracing")]`.
+// - `tracing` macros with log levels (`trace!`, `debug!`, `warn!`, `info`, `error`) should not be
+//   used *directly*. You should use the wrapped `tracing` macros which gate the actual invocations
+//   behind `feature = "tracing"`.
 // - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature =
 //   "tracing", instrument(..))]`.
 #[cfg(feature = "tracing")]
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index d56f35f866cb8..2dd83d5938e9d 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -28,8 +28,6 @@ use std::{env, fs, io, str};
 use build_helper::ci::gha;
 use build_helper::exit;
 use termcolor::{ColorChoice, StandardStream, WriteColor};
-#[cfg(feature = "tracing")]
-use tracing::{debug, instrument, span, trace};
 use utils::build_stamp::BuildStamp;
 use utils::channel::GitInfo;
 
@@ -46,6 +44,8 @@ pub use core::builder::PathSet;
 pub use core::config::Config;
 pub use core::config::flags::{Flags, Subcommand};
 
+#[cfg(feature = "tracing")]
+use tracing::{instrument, span};
 pub use utils::change_tracker::{
     CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes,
 };
@@ -541,72 +541,71 @@ impl Build {
     /// Executes the entire build, as configured by the flags and configuration.
     #[cfg_attr(feature = "tracing", instrument(level = "debug", name = "Build::build", skip_all))]
     pub fn build(&mut self) {
-        #[cfg(feature = "tracing")]
         trace!("setting up job management");
         unsafe {
             crate::utils::job::setup(self);
         }
 
-        #[cfg(feature = "tracing")]
-        trace!("downloading rustfmt early");
-
         // Download rustfmt early so that it can be used in rust-analyzer configs.
+        trace!("downloading rustfmt early");
         let _ = &builder::Builder::new(self).initial_rustfmt();
 
-        #[cfg(feature = "tracing")]
-        let hardcoded_span =
-            span!(tracing::Level::DEBUG, "handling hardcoded subcommands (Format, Suggest, Perf)")
-                .entered();
-
-        // hardcoded subcommands
-        match &self.config.cmd {
-            Subcommand::Format { check, all } => {
-                return core::build_steps::format::format(
-                    &builder::Builder::new(self),
-                    *check,
-                    *all,
-                    &self.config.paths,
-                );
-            }
-            Subcommand::Suggest { run } => {
-                return core::build_steps::suggest::suggest(&builder::Builder::new(self), *run);
-            }
-            Subcommand::Perf { .. } => {
-                return core::build_steps::perf::perf(&builder::Builder::new(self));
-            }
-            _cmd => {
-                #[cfg(feature = "tracing")]
-                debug!(cmd = ?_cmd, "not a hardcoded subcommand; returning to normal handling");
+        // Handle hard-coded subcommands.
+        {
+            #[cfg(feature = "tracing")]
+            let _hardcoded_span = span!(
+                tracing::Level::DEBUG,
+                "handling hardcoded subcommands (Format, Suggest, Perf)"
+            )
+            .entered();
+
+            match &self.config.cmd {
+                Subcommand::Format { check, all } => {
+                    return core::build_steps::format::format(
+                        &builder::Builder::new(self),
+                        *check,
+                        *all,
+                        &self.config.paths,
+                    );
+                }
+                Subcommand::Suggest { run } => {
+                    return core::build_steps::suggest::suggest(&builder::Builder::new(self), *run);
+                }
+                Subcommand::Perf { .. } => {
+                    return core::build_steps::perf::perf(&builder::Builder::new(self));
+                }
+                _cmd => {
+                    debug!(cmd = ?_cmd, "not a hardcoded subcommand; returning to normal handling");
+                }
             }
-        }
 
-        #[cfg(feature = "tracing")]
-        drop(hardcoded_span);
-        #[cfg(feature = "tracing")]
-        debug!("handling subcommand normally");
+            debug!("handling subcommand normally");
+        }
 
         if !self.config.dry_run() {
             #[cfg(feature = "tracing")]
             let _real_run_span = span!(tracing::Level::DEBUG, "executing real run").entered();
 
+            // We first do a dry-run. This is a sanity-check to ensure that
+            // steps don't do anything expensive in the dry-run.
             {
                 #[cfg(feature = "tracing")]
                 let _sanity_check_span =
                     span!(tracing::Level::DEBUG, "(1) executing dry-run sanity-check").entered();
-
-                // We first do a dry-run. This is a sanity-check to ensure that
-                // steps don't do anything expensive in the dry-run.
                 self.config.dry_run = DryRun::SelfCheck;
                 let builder = builder::Builder::new(self);
                 builder.execute_cli();
             }
 
-            #[cfg(feature = "tracing")]
-            let _actual_run_span =
-                span!(tracing::Level::DEBUG, "(2) executing actual run").entered();
-            self.config.dry_run = DryRun::Disabled;
-            let builder = builder::Builder::new(self);
-            builder.execute_cli();
+            // Actual run.
+            {
+                #[cfg(feature = "tracing")]
+                let _actual_run_span =
+                    span!(tracing::Level::DEBUG, "(2) executing actual run").entered();
+                self.config.dry_run = DryRun::Disabled;
+                let builder = builder::Builder::new(self);
+                builder.execute_cli();
+            }
         } else {
             #[cfg(feature = "tracing")]
             let _dry_run_span = span!(tracing::Level::DEBUG, "executing dry run").entered();
diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs
index ea56932b40437..caef8ce3088a7 100644
--- a/src/bootstrap/src/utils/mod.rs
+++ b/src/bootstrap/src/utils/mod.rs
@@ -14,6 +14,8 @@ pub(crate) mod render_tests;
 pub(crate) mod shared_helpers;
 pub(crate) mod tarball;
 
+pub(crate) mod tracing;
+
 #[cfg(feature = "build-metrics")]
 pub(crate) mod metrics;
 
diff --git a/src/bootstrap/src/utils/tracing.rs b/src/bootstrap/src/utils/tracing.rs
new file mode 100644
index 0000000000000..e89decf9e5586
--- /dev/null
+++ b/src/bootstrap/src/utils/tracing.rs
@@ -0,0 +1,49 @@
+//! Wrapper macros for `tracing` macros to avoid having to write `cfg(feature = "tracing")`-gated
+//! `debug!`/`trace!` everytime, e.g.
+//!
+//! ```rust,ignore (example)
+//! #[cfg(feature = "tracing")]
+//! trace!("...");
+//! ```
+//!
+//! When `feature = "tracing"` is inactive, these macros expand to nothing.
+
+#[macro_export]
+macro_rules! trace {
+    ($($tokens:tt)*) => {
+        #[cfg(feature = "tracing")]
+        ::tracing::trace!($($tokens)*)
+    }
+}
+
+#[macro_export]
+macro_rules! debug {
+    ($($tokens:tt)*) => {
+        #[cfg(feature = "tracing")]
+        ::tracing::debug!($($tokens)*)
+    }
+}
+
+#[macro_export]
+macro_rules! warn {
+    ($($tokens:tt)*) => {
+        #[cfg(feature = "tracing")]
+        ::tracing::warn!($($tokens)*)
+    }
+}
+
+#[macro_export]
+macro_rules! info {
+    ($($tokens:tt)*) => {
+        #[cfg(feature = "tracing")]
+        ::tracing::info!($($tokens)*)
+    }
+}
+
+#[macro_export]
+macro_rules! error {
+    ($($tokens:tt)*) => {
+        #[cfg(feature = "tracing")]
+        ::tracing::error!($($tokens)*)
+    }
+}
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 7eb1b8df2333d..3abd538d372c4 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -330,7 +330,7 @@ the source.
 
 ## `--show-type-layout`: add a section to each type's docs describing its memory layout
 
-* Tracking issue: [#113248](https://github.com/rust-lang/rust/issues/113248)
+ * Tracking issue: [#113248](https://github.com/rust-lang/rust/issues/113248)
 
 Using this flag looks like this:
 
@@ -526,9 +526,10 @@ use `-o -`.
 
 ### json
 
+ * Tracking Issue: [#76578](https://github.com/rust-lang/rust/issues/76578)
+
 `--output-format json` emits documentation in the experimental
-[JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). `--output-format html` has no effect,
-and is also accepted on stable toolchains.
+[JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/).
 
 JSON Output for toolchain crates (`std`, `alloc`, `core`, `test`, and `proc_macro`)
 is available via the `rust-docs-json` rustup component.
@@ -546,11 +547,11 @@ information.
 
 ### doctest
 
+ * Tracking issue: [#134529](https://github.com/rust-lang/rust/issues/134529)
+
 `--output-format doctest` emits JSON on stdout which gives you information about doctests in the
 provided crate.
 
-Tracking issue: [#134529](https://github.com/rust-lang/rust/issues/134529)
-
 You can use this option like this:
 
 ```bash
@@ -606,6 +607,11 @@ The generated output (formatted) will look like this:
    * `doctest_code` is the code modified by rustdoc that will be run. If there is a fatal syntax error, this field will not be present.
    * `name` is the name generated by rustdoc which represents this doctest.
 
+### html
+
+`--output-format html` has no effect, as the default output is HTML. This is
+accepted on stable, even though the other options for this flag aren't.
+
 ## `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
 
  * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245)
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index bfd5cb7764fd4..a348c6c5678b9 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -196,15 +196,13 @@ function switchDisplayedElement(elemToDisplay) {
     removeClass(el, "hidden");
 
     const mainHeading = elemToDisplay.querySelector(".main-heading");
-    // @ts-expect-error
-    if (mainHeading && searchState.rustdocToolbar) {
-        // @ts-expect-error
-        if (searchState.rustdocToolbar.parentElement) {
-            // @ts-expect-error
-            searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar);
+    if (mainHeading && window.searchState.rustdocToolbar) {
+        if (window.searchState.rustdocToolbar.parentElement) {
+            window.searchState.rustdocToolbar.parentElement.removeChild(
+                window.searchState.rustdocToolbar,
+            );
         }
-        // @ts-expect-error
-        mainHeading.appendChild(searchState.rustdocToolbar);
+        mainHeading.appendChild(window.searchState.rustdocToolbar);
     }
 }
 
@@ -212,7 +210,12 @@ function browserSupportsHistoryApi() {
     return window.history && typeof window.history.pushState === "function";
 }
 
-// @ts-expect-error
+/**
+ * Download CSS from the web without making it the active stylesheet.
+ * We use this in the settings popover so that you don't get FOUC when switching.
+ *
+ * @param {string} cssUrl
+ */
 function preLoadCss(cssUrl) {
     // https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload
     const link = document.createElement("link");
@@ -225,7 +228,11 @@ function preLoadCss(cssUrl) {
 (function() {
     const isHelpPage = window.location.pathname.endsWith("/help.html");
 
-    // @ts-expect-error
+    /**
+     * Run a JavaScript file asynchronously.
+     * @param {string} url
+     * @param {function(): any} errorCallback
+     */
     function loadScript(url, errorCallback) {
         const script = document.createElement("script");
         script.src = url;
@@ -235,13 +242,12 @@ function preLoadCss(cssUrl) {
         document.head.append(script);
     }
 
-    if (getSettingsButton()) {
-        // @ts-expect-error
-        getSettingsButton().onclick = event => {
+    const settingsButton = getSettingsButton();
+    if (settingsButton) {
+        settingsButton.onclick = event => {
             if (event.ctrlKey || event.altKey || event.metaKey) {
                 return;
             }
-            // @ts-expect-error
             window.hideAllModals(false);
             addClass(getSettingsButton(), "rotate");
             event.preventDefault();
@@ -470,7 +476,6 @@ function preLoadCss(cssUrl) {
                     }
                     return onEachLazy(implElem.parentElement.parentElement.querySelectorAll(
                         `[id^="${assocId}"]`),
-                        // @ts-expect-error
                         item => {
                             const numbered = /^(.+?)-([0-9]+)$/.exec(item.id);
                             if (item.id === assocId || (numbered && numbered[1] === assocId)) {
@@ -522,7 +527,6 @@ function preLoadCss(cssUrl) {
         ev.preventDefault();
         // @ts-expect-error
         searchState.defocus();
-        // @ts-expect-error
         window.hideAllModals(true); // true = reset focus for tooltips
     }
 
@@ -687,7 +691,6 @@ function preLoadCss(cssUrl) {
             //
             // By the way, this is only used by and useful for traits implemented automatically
             // (like "Send" and "Sync").
-            // @ts-expect-error
             onEachLazy(synthetic_implementors.getElementsByClassName("impl"), el => {
                 const aliases = el.getAttribute("data-aliases");
                 if (!aliases) {
@@ -740,7 +743,6 @@ function preLoadCss(cssUrl) {
                 code.innerHTML = struct[TEXT_IDX];
                 addClass(code, "code-header");
 
-                // @ts-expect-error
                 onEachLazy(code.getElementsByTagName("a"), elem => {
                     const href = elem.getAttribute("href");
 
@@ -886,7 +888,6 @@ function preLoadCss(cssUrl) {
             const template = document.createElement("template");
             template.innerHTML = text;
 
-            // @ts-expect-error
             onEachLazy(template.content.querySelectorAll("a"), elem => {
                 const href = elem.getAttribute("href");
 
@@ -894,7 +895,6 @@ function preLoadCss(cssUrl) {
                     elem.setAttribute("href", window.rootPath + href);
                 }
             });
-            // @ts-expect-error
             onEachLazy(template.content.querySelectorAll("[id]"), el => {
                 let i = 0;
                 if (idMap.has(el.id)) {
@@ -912,7 +912,6 @@ function preLoadCss(cssUrl) {
                     const oldHref = `#${el.id}`;
                     const newHref = `#${el.id}-${i}`;
                     el.id = `${el.id}-${i}`;
-                    // @ts-expect-error
                     onEachLazy(template.content.querySelectorAll("a[href]"), link => {
                         if (link.getAttribute("href") === oldHref) {
                             link.href = newHref;
@@ -933,7 +932,6 @@ function preLoadCss(cssUrl) {
                 // @ts-expect-error
                 sidebarTraitList.append(li);
             } else {
-                // @ts-expect-error
                 onEachLazy(templateAssocItems, item => {
                     let block = hasClass(item, "associatedtype") ? associatedTypes : (
                         hasClass(item, "associatedconstant") ? associatedConstants : (
@@ -1040,7 +1038,6 @@ function preLoadCss(cssUrl) {
     function expandAllDocs() {
         const innerToggle = document.getElementById(toggleAllDocsId);
         removeClass(innerToggle, "will-expand");
-        // @ts-expect-error
         onEachLazy(document.getElementsByClassName("toggle"), e => {
             if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) {
                 e.open = true;
@@ -1053,7 +1050,6 @@ function preLoadCss(cssUrl) {
     function collapseAllDocs() {
         const innerToggle = document.getElementById(toggleAllDocsId);
         addClass(innerToggle, "will-expand");
-        // @ts-expect-error
         onEachLazy(document.getElementsByClassName("toggle"), e => {
             if (e.parentNode.id !== "implementations-list" ||
                 (!hasClass(e, "implementors-toggle") &&
@@ -1092,7 +1088,6 @@ function preLoadCss(cssUrl) {
         function setImplementorsTogglesOpen(id, open) {
             const list = document.getElementById(id);
             if (list !== null) {
-                // @ts-expect-error
                 onEachLazy(list.getElementsByClassName("implementors-toggle"), e => {
                     e.open = open;
                 });
@@ -1104,7 +1099,6 @@ function preLoadCss(cssUrl) {
             setImplementorsTogglesOpen("blanket-implementations-list", false);
         }
 
-        // @ts-expect-error
         onEachLazy(document.getElementsByClassName("toggle"), e => {
             if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
                 e.open = true;
@@ -1124,7 +1118,6 @@ function preLoadCss(cssUrl) {
         }
         onEachLazy(document.querySelectorAll(
             ":not(.scraped-example) > .example-wrap > pre:not(.example-line-numbers)",
-        // @ts-expect-error
         ), x => {
             const parent = x.parentNode;
             const line_numbers = parent.querySelectorAll(".example-line-numbers");
@@ -1145,7 +1138,6 @@ function preLoadCss(cssUrl) {
 
     // @ts-expect-error
     window.rustdoc_remove_line_numbers_from_examples = () => {
-        // @ts-expect-error
         onEachLazy(document.querySelectorAll(".example-wrap > .example-line-numbers"), x => {
             x.parentNode.removeChild(x);
         });
@@ -1157,16 +1149,13 @@ function preLoadCss(cssUrl) {
     }
 
     function showSidebar() {
-        // @ts-expect-error
         window.hideAllModals(false);
         const sidebar = document.getElementsByClassName("sidebar")[0];
-        // @ts-expect-error
         addClass(sidebar, "shown");
     }
 
     function hideSidebar() {
         const sidebar = document.getElementsByClassName("sidebar")[0];
-        // @ts-expect-error
         removeClass(sidebar, "shown");
     }
 
@@ -1193,7 +1182,6 @@ function preLoadCss(cssUrl) {
         mainElem.addEventListener("click", hideSidebar);
     }
 
-    // @ts-expect-error
     onEachLazy(document.querySelectorAll("a[href^='#']"), el => {
         // For clicks on internal links (<A> tags with a hash property), we expand the section we're
         // jumping to *before* jumping there. We can't do this in onHashChange, because it changes
@@ -1204,7 +1192,6 @@ function preLoadCss(cssUrl) {
         });
     });
 
-    // @ts-expect-error
     onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"), el => {
         // @ts-expect-error
         el.addEventListener("click", e => {
@@ -1241,7 +1228,6 @@ function preLoadCss(cssUrl) {
             clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);
             return;
         }
-        // @ts-expect-error
         window.hideAllModals(false);
         const wrapper = document.createElement("div");
         if (notable_ty) {
@@ -1422,7 +1408,6 @@ function preLoadCss(cssUrl) {
         }
     }
 
-    // @ts-expect-error
     onEachLazy(document.getElementsByClassName("tooltip"), e => {
         e.onclick = () => {
             e.TOOLTIP_FORCE_VISIBLE = e.TOOLTIP_FORCE_VISIBLE ? false : true;
@@ -1527,7 +1512,6 @@ function preLoadCss(cssUrl) {
             // @ts-expect-error
             !getSettingsButton().contains(event.relatedTarget)
         ) {
-            // @ts-expect-error
             window.hidePopoverMenus();
         }
     }
@@ -1626,10 +1610,8 @@ function preLoadCss(cssUrl) {
      *
      * Pass "true" to reset focus for tooltip popovers.
      */
-    // @ts-expect-error
     window.hideAllModals = switchFocus => {
         hideSidebar();
-        // @ts-expect-error
         window.hidePopoverMenus();
         hideTooltip(switchFocus);
     };
@@ -1637,9 +1619,7 @@ function preLoadCss(cssUrl) {
     /**
      * Hide all the popover menus.
      */
-    // @ts-expect-error
     window.hidePopoverMenus = () => {
-        // @ts-expect-error
         onEachLazy(document.querySelectorAll("rustdoc-toolbar .popover"), elem => {
             elem.style.display = "none";
         });
@@ -1708,7 +1688,6 @@ function preLoadCss(cssUrl) {
             if (shouldShowHelp) {
                 showHelp();
             } else {
-                // @ts-expect-error
                 window.hidePopoverMenus();
             }
         });
@@ -1780,30 +1759,42 @@ function preLoadCss(cssUrl) {
         });
     }
 
-    // Pointer capture.
-    //
-    // Resizing is a single-pointer gesture. Any secondary pointer is ignored
-    // @ts-expect-error
+    /**
+     * Pointer capture.
+     *
+     * Resizing is a single-pointer gesture. Any secondary pointer is ignored
+     *
+     * @type {null|number}
+     */
     let currentPointerId = null;
 
-    // "Desired" sidebar size.
-    //
-    // This is stashed here for window resizing. If the sidebar gets
-    // shrunk to maintain BODY_MIN, and then the user grows the window again,
-    // it gets the sidebar to restore its size.
-    // @ts-expect-error
+    /**
+     * "Desired" sidebar size.
+     *
+     * This is stashed here for window resizing. If the sidebar gets
+     * shrunk to maintain BODY_MIN, and then the user grows the window again,
+     * it gets the sidebar to restore its size.
+     *
+     * @type {null|number}
+     */
     let desiredSidebarSize = null;
 
-    // Sidebar resize debouncer.
-    //
-    // The sidebar itself is resized instantly, but the body HTML can be too
-    // big for that, causing reflow jank. To reduce this, we queue up a separate
-    // animation frame and throttle it.
+    /**
+     * Sidebar resize debouncer.
+     *
+     * The sidebar itself is resized instantly, but the body HTML can be too
+     * big for that, causing reflow jank. To reduce this, we queue up a separate
+     * animation frame and throttle it.
+     *
+     * @type {false|ReturnType<typeof setTimeout>}
+     */
     let pendingSidebarResizingFrame = false;
 
-    // If this page has no sidebar at all, bail out.
+    /** @type {HTMLElement|null} */
     const resizer = document.querySelector(".sidebar-resizer");
+    /** @type {HTMLElement|null} */
     const sidebar = document.querySelector(".sidebar");
+    // If this page has no sidebar at all, bail out.
     if (!resizer || !sidebar) {
         return;
     }
@@ -1820,11 +1811,9 @@ function preLoadCss(cssUrl) {
     // from settings.js, which uses a separate function. It's done here because
     // the minimum sidebar size is rather uncomfortable, and it must pass
     // through that size when using the shrink-to-nothing gesture.
-    function hideSidebar() {
+    const hideSidebar = function() {
         if (isSrcPage) {
-            // @ts-expect-error
             window.rustdocCloseSourceSidebar();
-            // @ts-expect-error
             updateLocalStorage("src-sidebar-width", null);
             // [RUSTDOCIMPL] CSS variable fast path
             //
@@ -1837,22 +1826,17 @@ function preLoadCss(cssUrl) {
             //
             // So, to clear it, we need to clear all three.
             document.documentElement.style.removeProperty("--src-sidebar-width");
-            // @ts-expect-error
             sidebar.style.removeProperty("--src-sidebar-width");
-            // @ts-expect-error
             resizer.style.removeProperty("--src-sidebar-width");
         } else {
             addClass(document.documentElement, "hide-sidebar");
             updateLocalStorage("hide-sidebar", "true");
-            // @ts-expect-error
             updateLocalStorage("desktop-sidebar-width", null);
             document.documentElement.style.removeProperty("--desktop-sidebar-width");
-            // @ts-expect-error
             sidebar.style.removeProperty("--desktop-sidebar-width");
-            // @ts-expect-error
             resizer.style.removeProperty("--desktop-sidebar-width");
         }
-    }
+    };
 
     // Call this function to show the sidebar from the resize handle.
     // On docs pages, this can only happen if the user has grabbed the resize
@@ -1860,15 +1844,14 @@ function preLoadCss(cssUrl) {
     // the visible range without releasing it. You can, however, grab the
     // resize handle on a source page with the sidebar closed, because it
     // remains visible all the time on there.
-    function showSidebar() {
+    const showSidebar = function() {
         if (isSrcPage) {
-            // @ts-expect-error
             window.rustdocShowSourceSidebar();
         } else {
             removeClass(document.documentElement, "hide-sidebar");
             updateLocalStorage("hide-sidebar", "false");
         }
-    }
+    };
 
     /**
      * Call this to set the correct CSS variable and setting.
@@ -1876,44 +1859,40 @@ function preLoadCss(cssUrl) {
      *
      * @param {number} size - CSS px width of the sidebar.
      */
-    function changeSidebarSize(size) {
+    const changeSidebarSize = function(size) {
         if (isSrcPage) {
-            // @ts-expect-error
-            updateLocalStorage("src-sidebar-width", size);
+            updateLocalStorage("src-sidebar-width", size.toString());
             // [RUSTDOCIMPL] CSS variable fast path
             //
             // While this property is set on the HTML element at load time,
             // because the sidebar isn't actually loaded yet,
             // we scope this update to the sidebar to avoid hitting a slow
             // path in WebKit.
-            // @ts-expect-error
             sidebar.style.setProperty("--src-sidebar-width", size + "px");
-            // @ts-expect-error
             resizer.style.setProperty("--src-sidebar-width", size + "px");
         } else {
-            // @ts-expect-error
-            updateLocalStorage("desktop-sidebar-width", size);
-            // @ts-expect-error
+            updateLocalStorage("desktop-sidebar-width", size.toString());
             sidebar.style.setProperty("--desktop-sidebar-width", size + "px");
-            // @ts-expect-error
             resizer.style.setProperty("--desktop-sidebar-width", size + "px");
         }
-    }
+    };
 
     // Check if the sidebar is hidden. Since src pages and doc pages have
     // different settings, this function has to check that.
-    function isSidebarHidden() {
+    const isSidebarHidden = function() {
         return isSrcPage ?
             !hasClass(document.documentElement, "src-sidebar-expanded") :
             hasClass(document.documentElement, "hide-sidebar");
-    }
+    };
 
-    // Respond to the resize handle event.
-    // This function enforces size constraints, and implements the
-    // shrink-to-nothing gesture based on thresholds defined above.
-    // @ts-expect-error
-    function resize(e) {
-        // @ts-expect-error
+    /**
+     * Respond to the resize handle event.
+     * This function enforces size constraints, and implements the
+     * shrink-to-nothing gesture based on thresholds defined above.
+     *
+     * @param {PointerEvent} e
+     */
+    const resize = function(e) {
         if (currentPointerId === null || currentPointerId !== e.pointerId) {
             return;
         }
@@ -1931,97 +1910,83 @@ function preLoadCss(cssUrl) {
             changeSidebarSize(constrainedPos);
             desiredSidebarSize = constrainedPos;
             if (pendingSidebarResizingFrame !== false) {
-                // @ts-expect-error
                 clearTimeout(pendingSidebarResizingFrame);
             }
-            // @ts-expect-error
             pendingSidebarResizingFrame = setTimeout(() => {
-                // @ts-expect-error
                 if (currentPointerId === null || pendingSidebarResizingFrame === false) {
                     return;
                 }
                 pendingSidebarResizingFrame = false;
                 document.documentElement.style.setProperty(
                     "--resizing-sidebar-width",
-                    // @ts-expect-error
                     desiredSidebarSize + "px",
                 );
             }, 100);
         }
-    }
+    };
     // Respond to the window resize event.
     window.addEventListener("resize", () => {
         if (window.innerWidth < RUSTDOC_MOBILE_BREAKPOINT) {
             return;
         }
         stopResize();
-        // @ts-expect-error
-        if (desiredSidebarSize >= (window.innerWidth - BODY_MIN)) {
+        if (desiredSidebarSize !== null && desiredSidebarSize >= (window.innerWidth - BODY_MIN)) {
             changeSidebarSize(window.innerWidth - BODY_MIN);
-        // @ts-expect-error
         } else if (desiredSidebarSize !== null && desiredSidebarSize > SIDEBAR_MIN) {
-            // @ts-expect-error
             changeSidebarSize(desiredSidebarSize);
         }
     });
-    // @ts-expect-error
-    function stopResize(e) {
-        // @ts-expect-error
+
+    /**
+     * @param {PointerEvent=} e
+     */
+    const stopResize = function(e) {
         if (currentPointerId === null) {
             return;
         }
         if (e) {
             e.preventDefault();
         }
-        // @ts-expect-error
         desiredSidebarSize = sidebar.getBoundingClientRect().width;
-        // @ts-expect-error
         removeClass(resizer, "active");
         window.removeEventListener("pointermove", resize, false);
         window.removeEventListener("pointerup", stopResize, false);
         removeClass(document.documentElement, "sidebar-resizing");
         document.documentElement.style.removeProperty( "--resizing-sidebar-width");
-        // @ts-expect-error
         if (resizer.releasePointerCapture) {
-            // @ts-expect-error
             resizer.releasePointerCapture(currentPointerId);
             currentPointerId = null;
         }
-    }
-    // @ts-expect-error
-    function initResize(e) {
-        // @ts-expect-error
+    };
+
+    /**
+     * @param {PointerEvent} e
+     */
+    const initResize = function(e) {
         if (currentPointerId !== null || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0) {
             return;
         }
-        // @ts-expect-error
         if (resizer.setPointerCapture) {
-            // @ts-expect-error
             resizer.setPointerCapture(e.pointerId);
-            // @ts-expect-error
             if (!resizer.hasPointerCapture(e.pointerId)) {
                 // unable to capture pointer; something else has it
                 // on iOS, this usually means you long-clicked a link instead
-                // @ts-expect-error
                 resizer.releasePointerCapture(e.pointerId);
                 return;
             }
             currentPointerId = e.pointerId;
         }
-        // @ts-expect-error
         window.hideAllModals(false);
         e.preventDefault();
         window.addEventListener("pointermove", resize, false);
         window.addEventListener("pointercancel", stopResize, false);
         window.addEventListener("pointerup", stopResize, false);
-        // @ts-expect-error
         addClass(resizer, "active");
         addClass(document.documentElement, "sidebar-resizing");
-        // @ts-expect-error
         const pos = e.clientX - sidebar.offsetLeft - 3;
         document.documentElement.style.setProperty( "--resizing-sidebar-width", pos + "px");
         desiredSidebarSize = null;
-    }
+    };
     resizer.addEventListener("pointerdown", initResize, false);
 }());
 
@@ -2029,8 +1994,13 @@ function preLoadCss(cssUrl) {
 // and the copy buttons on the code examples.
 (function() {
     // Common functions to copy buttons.
-    // @ts-expect-error
+    /**
+     * @param {string|null} content
+     */
     function copyContentToClipboard(content) {
+        if (content === null) {
+            return;
+        }
         const el = document.createElement("textarea");
         el.value = content;
         el.setAttribute("readonly", "");
@@ -2044,15 +2014,17 @@ function preLoadCss(cssUrl) {
         document.body.removeChild(el);
     }
 
-    // @ts-expect-error
+    /**
+     * @param {HTMLElement & {reset_button_timeout?: ReturnType<typeof setTimeout>}} button
+     */
     function copyButtonAnimation(button) {
         button.classList.add("clicked");
 
         if (button.reset_button_timeout !== undefined) {
-            window.clearTimeout(button.reset_button_timeout);
+            clearTimeout(button.reset_button_timeout);
         }
 
-        button.reset_button_timeout = window.setTimeout(() => {
+        button.reset_button_timeout = setTimeout(() => {
             button.reset_button_timeout = undefined;
             button.classList.remove("clicked");
         }, 1000);
@@ -2067,9 +2039,7 @@ function preLoadCss(cssUrl) {
         // Most page titles are '<Item> in <path::to::module> - Rust', except
         // modules (which don't have the first part) and keywords/primitives
         // (which don't have a module path)
-        // @ts-expect-error
-        const title = document.querySelector("title").textContent.replace(" - Rust", "");
-        const [item, module] = title.split(" in ");
+        const [item, module] = document.title.split(" in ");
         const path = [item];
         if (module !== undefined) {
             path.unshift(module);
@@ -2079,8 +2049,10 @@ function preLoadCss(cssUrl) {
         copyButtonAnimation(but);
     };
 
-    // Copy buttons on code examples.
-    // @ts-expect-error
+    /**
+     * Copy buttons on code examples.
+     * @param {HTMLElement|null} codeElem
+     */
     function copyCode(codeElem) {
         if (!codeElem) {
             // Should never happen, but the world is a dark and dangerous place.
@@ -2089,23 +2061,34 @@ function preLoadCss(cssUrl) {
         copyContentToClipboard(codeElem.textContent);
     }
 
-    // @ts-expect-error
+    /**
+     * @param {UIEvent} event
+     * @returns {HTMLElement|null}
+     */
     function getExampleWrap(event) {
-        let elem = event.target;
-        while (!hasClass(elem, "example-wrap")) {
-            if (elem === document.body ||
-                elem.tagName === "A" ||
-                elem.tagName === "BUTTON" ||
-                hasClass(elem, "docblock")
-            ) {
-                return null;
+        const target = event.target;
+        if (target instanceof HTMLElement) {
+            /** @type {HTMLElement|null} */
+            let elem = target;
+            while (elem !== null && !hasClass(elem, "example-wrap")) {
+                if (elem === document.body ||
+                    elem.tagName === "A" ||
+                    elem.tagName === "BUTTON" ||
+                    hasClass(elem, "docblock")
+                ) {
+                    return null;
+                }
+                elem = elem.parentElement;
             }
-            elem = elem.parentElement;
+            return elem;
+        } else {
+            return null;
         }
-        return elem;
     }
 
-    // @ts-expect-error
+    /**
+     * @param {UIEvent} event
+     */
     function addCopyButton(event) {
         const elem = getExampleWrap(event);
         if (elem === null) {
@@ -2132,15 +2115,17 @@ function preLoadCss(cssUrl) {
         });
         parent.appendChild(copyButton);
 
-        if (!elem.parentElement.classList.contains("scraped-example")) {
+        if (!elem.parentElement || !elem.parentElement.classList.contains("scraped-example") ||
+            !window.updateScrapedExample) {
             return;
         }
         const scrapedWrapped = elem.parentElement;
-        // @ts-expect-error
         window.updateScrapedExample(scrapedWrapped, parent);
     }
 
-    // @ts-expect-error
+    /**
+     * @param {UIEvent} event
+     */
     function showHideCodeExampleButtons(event) {
         const elem = getExampleWrap(event);
         if (elem === null) {
@@ -2159,7 +2144,6 @@ function preLoadCss(cssUrl) {
         buttons.classList.toggle("keep-visible");
     }
 
-    // @ts-expect-error
     onEachLazy(document.querySelectorAll(".docblock .example-wrap"), elem => {
         elem.addEventListener("mouseover", addCopyButton);
         elem.addEventListener("click", showHideCodeExampleButtons);
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index 18a3e22113b8b..acea7828e86a9 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -20,6 +20,28 @@ declare global {
          * As a multi-page application, we know this never changes once set.
          */
         currentCrate: string|null;
+        /**
+         * Hide popovers, tooltips, or the mobile sidebar.
+         */
+        hideAllModals: function(boolean),
+        /**
+         * Hide popovers, but leave other modals alone.
+         */
+        hidePopoverMenus: function(),
+        /**
+         * Hide the source page sidebar. If it's already closed,
+         * or if this is a docs page, this function does nothing.
+         */
+        rustdocCloseSourceSidebar: function(),
+        /**
+         * Show the source page sidebar. If it's already opened,
+         * or if this is a docs page, this function does nothing.
+         */
+        rustdocShowSourceSidebar: function(),
+        /**
+         * Set up event listeners for a scraped source example.
+         */
+        updateScrapedExample?: function(HTMLElement, HTMLElement),
     }
     interface HTMLElement {
         /** Used by the popover tooltip code. */
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 662e951069973..121a43e3d92e2 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -4732,10 +4732,8 @@ function printTab(nb) {
         // Corrections only kick in on type-based searches.
         const correctionsElem = document.getElementsByClassName("search-corrections");
         if (isTypeSearch) {
-            // @ts-expect-error
             removeClass(correctionsElem[0], "hidden");
         } else {
-            // @ts-expect-error
             addClass(correctionsElem[0], "hidden");
         }
     } else if (nb !== 0) {
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 10369e77320fe..3042373fb096f 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -59,7 +59,7 @@ function hasClass(elem, className) {
  * Add a class to a DOM Element. If `elem` is null,
  * does nothing. This function is idempotent.
  *
- * @param {HTMLElement|null} elem
+ * @param {Element|null} elem
  * @param {string} className
  */
 function addClass(elem, className) {
@@ -72,7 +72,7 @@ function addClass(elem, className) {
  * Remove a class from a DOM Element. If `elem` is null,
  * does nothing. This function is idempotent.
  *
- * @param {HTMLElement|null} elem
+ * @param {Element|null} elem
  * @param {string} className
  */
 // eslint-disable-next-line no-unused-vars
@@ -85,7 +85,7 @@ function removeClass(elem, className) {
 /**
  * Run a callback for every element of an Array.
  * @param {Array<?>}                       arr  - The array to iterate over
- * @param {function(?): boolean|undefined} func - The callback
+ * @param {function(?): boolean|void} func - The callback
  */
 function onEach(arr, func) {
     for (const elem of arr) {
@@ -103,7 +103,7 @@ function onEach(arr, func) {
  * https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
  * https://developer.mozilla.org/en-US/docs/Web/API/NodeList
  * @param {NodeList|HTMLCollection} lazyArray  - An array to iterate over
- * @param {function(?): boolean}    func       - The callback
+ * @param {function(?): boolean|void}    func       - The callback
  */
 // eslint-disable-next-line no-unused-vars
 function onEachLazy(lazyArray, func) {
@@ -119,11 +119,15 @@ function onEachLazy(lazyArray, func) {
  * If localStorage is disabled, this function does nothing.
  *
  * @param {string} name
- * @param {string} value
+ * @param {string|null} value
  */
 function updateLocalStorage(name, value) {
     try {
-        window.localStorage.setItem("rustdoc-" + name, value);
+        if (value === null) {
+            window.localStorage.removeItem("rustdoc-" + name);
+        } else {
+            window.localStorage.setItem("rustdoc-" + name, value);
+        }
     } catch (e) {
         // localStorage is not accessible, do nothing
     }
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 2eb09bac8d881..798f4575c2e10 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -362,18 +362,21 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 defaultness: ld,
                 sig: lf,
                 generics: lg,
+                contract: lc,
                 body: lb,
             }),
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
                 generics: rg,
+                contract: rc,
                 body: rb,
             }),
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
                 && eq_generics(lg, rg)
+                && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
         },
         (Mod(lu, lmk), Mod(ru, rmk)) => {
@@ -497,18 +500,21 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
                 defaultness: ld,
                 sig: lf,
                 generics: lg,
+                contract: lc,
                 body: lb,
             }),
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
                 generics: rg,
+                contract: rc,
                 body: rb,
             }),
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
                 && eq_generics(lg, rg)
+                && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
         },
         (
@@ -559,18 +565,21 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
                 defaultness: ld,
                 sig: lf,
                 generics: lg,
+                contract: lc,
                 body: lb,
             }),
             Fn(box ast::Fn {
                 defaultness: rd,
                 sig: rf,
                 generics: rg,
+                contract: rc,
                 body: rb,
             }),
         ) => {
             eq_defaultness(*ld, *rd)
                 && eq_fn_sig(lf, rf)
                 && eq_generics(lg, rg)
+                && eq_opt_fn_contract(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
         },
         (
@@ -653,6 +662,17 @@ pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool {
         && eq_ext(&l.ext, &r.ext)
 }
 
+pub fn eq_opt_fn_contract(l: &Option<P<FnContract>>, r: &Option<P<FnContract>>) -> bool {
+    match (l, r) {
+        (Some(l), Some(r)) => {
+            eq_expr_opt(l.requires.as_ref(), r.requires.as_ref())
+            && eq_expr_opt(l.ensures.as_ref(), r.ensures.as_ref())
+        }
+        (None, None) => true,
+        (Some(_), None) | (None, Some(_)) => false,
+    }
+}
+
 pub fn eq_generics(l: &Generics, r: &Generics) -> bool {
     over(&l.params, &r.params, eq_generic_param)
         && over(&l.where_clause.predicates, &r.where_clause.predicates, |l, r| {
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 0aaef91e48a6d..5a3a3d0cedc42 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -179,7 +179,7 @@ fn check_rvalue<'tcx>(
                 ))
             }
         },
-        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbChecks, _)
+        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::UbChecks | NullOp::ContractChecks, _)
         | Rvalue::ShallowInitBox(_, _) => Ok(()),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 4735db48e81f8..6bd1076a8a848 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -1150,6 +1150,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
         interp_ok(ecx.tcx.sess.ub_checks())
     }
 
+    #[inline(always)]
+    fn contract_checks(ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool> {
+        interp_ok(ecx.tcx.sess.contract_checks())
+    }
+
     #[inline(always)]
     fn thread_local_static_pointer(
         ecx: &mut MiriInterpCx<'tcx>,
diff --git a/tests/crashes/135124.rs b/tests/crashes/135124.rs
deleted file mode 100644
index d6655cb46fac2..0000000000000
--- a/tests/crashes/135124.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #135124
-trait A  {
-    fn y(&self)
-    {
-        fn call() -> impl Sized {}
-        self.fold(call());
-    }
-    fn fold(&self, &self._) {}
-}
diff --git a/tests/ui/check-cfg/cargo-build-script.stderr b/tests/ui/check-cfg/cargo-build-script.stderr
index df0bc47571c72..03a7156a4d69e 100644
--- a/tests/ui/check-cfg/cargo-build-script.stderr
+++ b/tests/ui/check-cfg/cargo-build-script.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `has_foo`
 LL | #[cfg(has_foo)]
    |       ^^^^^^^
    |
-   = help: expected names are: `has_bar` and 30 more
+   = help: expected names are: `has_bar` and 31 more
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr
index 58813a1f6770c..b83d1794984de 100644
--- a/tests/ui/check-cfg/cargo-feature.none.stderr
+++ b/tests/ui/check-cfg/cargo-feature.none.stderr
@@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `docsrs`, `feature`, and `test` and 30 more
+   = help: expected names are: `docsrs`, `feature`, and `test` and 31 more
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr
index 5a12be8133871..2cddcbbcd7f9e 100644
--- a/tests/ui/check-cfg/cargo-feature.some.stderr
+++ b/tests/ui/check-cfg/cargo-feature.some.stderr
@@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable`
 LL | #[cfg(tokio_unstable)]
    |       ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `CONFIG_NVME`, `docsrs`, `feature`, and `test` and 30 more
+   = help: expected names are: `CONFIG_NVME`, `docsrs`, `feature`, and `test` and 31 more
    = help: consider using a Cargo feature instead
    = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
             [lints.rust]
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
index 7c276c581707e..68e1259dbb842 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value`
 LL | #[cfg(value)]
    |       ^^^^^
    |
-   = help: expected names are: `bar`, `bee`, `cow`, and `foo` and 30 more
+   = help: expected names are: `bar`, `bee`, `cow`, and `foo` and 31 more
    = help: to expect this configuration use `--check-cfg=cfg(value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
index 9687a043e8322..138c7fc758494 100644
--- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value`
 LL | #[cfg(my_value)]
    |       ^^^^^^^^
    |
-   = help: expected names are: `bar` and `foo` and 30 more
+   = help: expected names are: `bar` and `foo` and 31 more
    = help: to expect this configuration use `--check-cfg=cfg(my_value)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index 10302f0a7e46a..af66cbd818946 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `feature` and 30 more
+   = help: expected names are: `feature` and 31 more
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index 10302f0a7e46a..af66cbd818946 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `feature` and 30 more
+   = help: expected names are: `feature` and 31 more
    = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 033aaef848f74..be4d7c7727636 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu`
 LL | #[cfg_attr(uu, unix)]
    |            ^^
    |
-   = help: expected names are: `feature` and 30 more
+   = help: expected names are: `feature` and 31 more
    = help: to expect this configuration use `--check-cfg=cfg(uu)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/raw-keywords.edition2015.stderr b/tests/ui/check-cfg/raw-keywords.edition2015.stderr
index f19ded9cb6715..8ca33e088fc94 100644
--- a/tests/ui/check-cfg/raw-keywords.edition2015.stderr
+++ b/tests/ui/check-cfg/raw-keywords.edition2015.stderr
@@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `r#false`
 LL | #[cfg(r#false)]
    |       ^^^^^^^
    |
-   = help: expected names are: `async`, `edition2015`, `edition2021`, and `r#true` and 30 more
+   = help: expected names are: `async`, `edition2015`, `edition2021`, and `r#true` and 31 more
    = help: to expect this configuration use `--check-cfg=cfg(r#false)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/raw-keywords.edition2021.stderr b/tests/ui/check-cfg/raw-keywords.edition2021.stderr
index 6096148a259b0..cce55720bdd18 100644
--- a/tests/ui/check-cfg/raw-keywords.edition2021.stderr
+++ b/tests/ui/check-cfg/raw-keywords.edition2021.stderr
@@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `r#false`
 LL | #[cfg(r#false)]
    |       ^^^^^^^
    |
-   = help: expected names are: `r#async`, `edition2015`, `edition2021`, and `r#true` and 30 more
+   = help: expected names are: `r#async`, `edition2015`, `edition2021`, and `r#true` and 31 more
    = help: to expect this configuration use `--check-cfg=cfg(r#false)`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
index a6584d777a3a6..989a01f224412 100644
--- a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
+++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_lib_cfg`
 LL |     cfg_macro::my_lib_macro!();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `feature` and 30 more
+   = help: expected names are: `feature` and 31 more
    = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
    = help: try referring to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg
    = help: the macro `cfg_macro::my_lib_macro` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro`
diff --git a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
index 914b5a0efe366..95d10e014f33b 100644
--- a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
+++ b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_lib_cfg`
 LL |     cfg_macro::my_lib_macro!();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `feature` and 30 more
+   = help: expected names are: `feature` and 31 more
    = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
    = help: try referring to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg
    = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)`
diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr
index 4ff90261158bc..000315443f810 100644
--- a/tests/ui/check-cfg/well-known-names.stderr
+++ b/tests/ui/check-cfg/well-known-names.stderr
@@ -5,6 +5,7 @@ LL | #[cfg(list_all_well_known_cfgs)]
    |       ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: expected names are: `clippy`
+`contract_checks`
 `debug_assertions`
 `doc`
 `doctest`
diff --git a/tests/ui/contracts/contract-annotation-limitations.rs b/tests/ui/contracts/contract-annotation-limitations.rs
new file mode 100644
index 0000000000000..10b3bacab5cfa
--- /dev/null
+++ b/tests/ui/contracts/contract-annotation-limitations.rs
@@ -0,0 +1,28 @@
+//! Test for some of the existing limitations and the current error messages.
+//! Some of these limitations may be removed in the future.
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+#![allow(dead_code)]
+
+/// Represent a 5-star system.
+struct Stars(u8);
+
+impl Stars {
+    fn is_valid(&self) -> bool {
+        self.0 <= 5
+    }
+}
+
+trait ParseStars {
+    #[core::contracts::ensures(|ret| ret.is_none_or(Stars::is_valid))]
+    //~^ ERROR contract annotations is only supported in functions with bodies
+    fn parse_string(input: String) -> Option<Stars>;
+
+    #[core::contracts::ensures(|ret| ret.is_none_or(Stars::is_valid))]
+    //~^ ERROR contract annotations is only supported in functions with bodies
+    fn parse<T>(input: T) -> Option<Stars> where T: for<'a> Into<&'a str>;
+}
+
+fn main() {
+}
diff --git a/tests/ui/contracts/contract-annotation-limitations.stderr b/tests/ui/contracts/contract-annotation-limitations.stderr
new file mode 100644
index 0000000000000..14338cf4b8687
--- /dev/null
+++ b/tests/ui/contracts/contract-annotation-limitations.stderr
@@ -0,0 +1,23 @@
+error: contract annotations is only supported in functions with bodies
+  --> $DIR/contract-annotation-limitations.rs:18:5
+   |
+LL |     #[core::contracts::ensures(|ret| ret.is_none_or(Stars::is_valid))]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: contract annotations is only supported in functions with bodies
+  --> $DIR/contract-annotation-limitations.rs:22:5
+   |
+LL |     #[core::contracts::ensures(|ret| ret.is_none_or(Stars::is_valid))]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-annotation-limitations.rs:4:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-generics.chk_const_fail.stderr b/tests/ui/contracts/contract-attributes-generics.chk_const_fail.stderr
new file mode 100644
index 0000000000000..0630811d4f7ea
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-generics.chk_const_fail.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-generics.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-generics.chk_fail_post.stderr b/tests/ui/contracts/contract-attributes-generics.chk_fail_post.stderr
new file mode 100644
index 0000000000000..0630811d4f7ea
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-generics.chk_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-generics.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-generics.chk_fail_pre.stderr b/tests/ui/contracts/contract-attributes-generics.chk_fail_pre.stderr
new file mode 100644
index 0000000000000..0630811d4f7ea
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-generics.chk_fail_pre.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-generics.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-generics.chk_pass.stderr b/tests/ui/contracts/contract-attributes-generics.chk_pass.stderr
new file mode 100644
index 0000000000000..0630811d4f7ea
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-generics.chk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-generics.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-generics.rs b/tests/ui/contracts/contract-attributes-generics.rs
new file mode 100644
index 0000000000000..fd79c6abedd85
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-generics.rs
@@ -0,0 +1,71 @@
+//! Test that contracts can be applied to generic functions.
+
+//@ revisions: unchk_pass chk_pass chk_fail_pre chk_fail_post chk_const_fail
+//
+//@ [unchk_pass] run-pass
+//@ [chk_pass] run-pass
+//
+//@ [chk_fail_pre] run-fail
+//@ [chk_fail_post] run-fail
+//@ [chk_const_fail] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_post] compile-flags: -Zcontract-checks=yes
+//@ [chk_const_fail] compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+use std::ops::Sub;
+
+/// Dummy fn contract that precondition fails for val < 0, and post-condition fail for val == 1
+#[core::contracts::requires(val > 0u8.into())]
+#[core::contracts::ensures(|ret| *ret > 0u8.into())]
+fn decrement<T>(val: T) -> T
+where T: PartialOrd + Sub<Output=T> + From<u8>
+{
+    val - 1u8.into()
+}
+
+/// Create a structure that takes a constant parameter.
+#[allow(dead_code)]
+struct Capped<const MAX: usize>(usize);
+
+/// Now declare a function to create stars which shouldn't exceed 5 stars.
+// Add redundant braces to ensure the built-in macro can handle this syntax.
+#[allow(unused_braces)]
+#[core::contracts::requires(num <= 5)]
+unsafe fn stars_unchecked(num: usize) -> Capped<{ 5 }> {
+    Capped(num)
+}
+
+
+fn main() {
+    check_decrement();
+    check_stars();
+}
+
+fn check_stars() {
+    // This should always pass.
+    let _ = unsafe { stars_unchecked(3) };
+
+    // This violates the contract.
+    #[cfg(any(unchk_pass, chk_const_fail))]
+    let _ = unsafe { stars_unchecked(10) };
+}
+
+fn check_decrement() {
+    // This should always pass
+    assert_eq!(decrement(10u8), 9u8);
+
+    // This should fail requires but pass with no contract check.
+    #[cfg(any(unchk_pass, chk_fail_pre))]
+    assert_eq!(decrement(-2i128), -3i128);
+
+    // This should fail ensures but pass with no contract check.
+    #[cfg(any(unchk_pass, chk_fail_post))]
+    assert_eq!(decrement(1i32), 0i32);
+}
diff --git a/tests/ui/contracts/contract-attributes-generics.unchk_pass.stderr b/tests/ui/contracts/contract-attributes-generics.unchk_pass.stderr
new file mode 100644
index 0000000000000..0630811d4f7ea
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-generics.unchk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-generics.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-nest.chk_fail_post.stderr b/tests/ui/contracts/contract-attributes-nest.chk_fail_post.stderr
new file mode 100644
index 0000000000000..9ca95b8bb01a4
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-nest.chk_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-nest.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-nest.chk_fail_pre.stderr b/tests/ui/contracts/contract-attributes-nest.chk_fail_pre.stderr
new file mode 100644
index 0000000000000..9ca95b8bb01a4
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-nest.chk_fail_pre.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-nest.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr b/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr
new file mode 100644
index 0000000000000..9ca95b8bb01a4
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-nest.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-nest.rs b/tests/ui/contracts/contract-attributes-nest.rs
new file mode 100644
index 0000000000000..e1e61b88f282e
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-nest.rs
@@ -0,0 +1,45 @@
+//@ revisions: unchk_pass unchk_fail_pre unchk_fail_post chk_pass chk_fail_pre chk_fail_post
+//
+//@ [unchk_pass] run-pass
+//@ [unchk_fail_pre] run-pass
+//@ [unchk_fail_post] run-pass
+//@ [chk_pass] run-pass
+//
+//@ [chk_fail_pre] run-fail
+//@ [chk_fail_post] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_post] compile-flags: -Zcontract-checks=no
+//
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_post] compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+#[core::contracts::requires(x.baz > 0)]
+#[core::contracts::ensures(|ret| *ret > 100)]
+fn nest(x: Baz) -> i32
+{
+    loop {
+        return x.baz + 50;
+    }
+}
+
+struct Baz { baz: i32 }
+
+const BAZ_PASS_PRE_POST: Baz = Baz { baz: 100 };
+#[cfg(any(unchk_fail_post, chk_fail_post))]
+const BAZ_FAIL_POST: Baz = Baz { baz: 10 };
+#[cfg(any(unchk_fail_pre, chk_fail_pre))]
+const BAZ_FAIL_PRE: Baz = Baz { baz: -10 };
+
+fn main() {
+    assert_eq!(nest(BAZ_PASS_PRE_POST), 150);
+    #[cfg(any(unchk_fail_pre, chk_fail_pre))]
+    nest(BAZ_FAIL_PRE);
+    #[cfg(any(unchk_fail_post, chk_fail_post))]
+    nest(BAZ_FAIL_POST);
+}
diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr
new file mode 100644
index 0000000000000..9ca95b8bb01a4
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-nest.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr
new file mode 100644
index 0000000000000..9ca95b8bb01a4
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-nest.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr
new file mode 100644
index 0000000000000..9ca95b8bb01a4
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-nest.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-tail.chk_fail_post.stderr b/tests/ui/contracts/contract-attributes-tail.chk_fail_post.stderr
new file mode 100644
index 0000000000000..f87e7e19fa3db
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-tail.chk_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-tail.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-tail.chk_fail_pre.stderr b/tests/ui/contracts/contract-attributes-tail.chk_fail_pre.stderr
new file mode 100644
index 0000000000000..f87e7e19fa3db
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-tail.chk_fail_pre.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-tail.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-tail.chk_pass.stderr b/tests/ui/contracts/contract-attributes-tail.chk_pass.stderr
new file mode 100644
index 0000000000000..f87e7e19fa3db
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-tail.chk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-tail.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-tail.rs b/tests/ui/contracts/contract-attributes-tail.rs
new file mode 100644
index 0000000000000..ce4a6be5b82f7
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-tail.rs
@@ -0,0 +1,43 @@
+//@ revisions: unchk_pass unchk_fail_pre unchk_fail_post chk_pass chk_fail_pre chk_fail_post
+//
+//@ [unchk_pass] run-pass
+//@ [unchk_fail_pre] run-pass
+//@ [unchk_fail_post] run-pass
+//@ [chk_pass] run-pass
+//
+//@ [chk_fail_pre] run-fail
+//@ [chk_fail_post] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_post] compile-flags: -Zcontract-checks=no
+//
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_post] compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+#[core::contracts::requires(x.baz > 0)]
+#[core::contracts::ensures(|ret| *ret > 100)]
+fn tail(x: Baz) -> i32
+{
+    x.baz + 50
+}
+
+struct Baz { baz: i32 }
+
+const BAZ_PASS_PRE_POST: Baz = Baz { baz: 100 };
+#[cfg(any(unchk_fail_post, chk_fail_post))]
+const BAZ_FAIL_POST: Baz = Baz { baz: 10 };
+#[cfg(any(unchk_fail_pre, chk_fail_pre))]
+const BAZ_FAIL_PRE: Baz = Baz { baz: -10 };
+
+fn main() {
+    assert_eq!(tail(BAZ_PASS_PRE_POST), 150);
+    #[cfg(any(unchk_fail_pre, chk_fail_pre))]
+    tail(BAZ_FAIL_PRE);
+    #[cfg(any(unchk_fail_post, chk_fail_post))]
+    tail(BAZ_FAIL_POST);
+}
diff --git a/tests/ui/contracts/contract-attributes-tail.unchk_fail_post.stderr b/tests/ui/contracts/contract-attributes-tail.unchk_fail_post.stderr
new file mode 100644
index 0000000000000..f87e7e19fa3db
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-tail.unchk_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-tail.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-tail.unchk_fail_pre.stderr b/tests/ui/contracts/contract-attributes-tail.unchk_fail_pre.stderr
new file mode 100644
index 0000000000000..f87e7e19fa3db
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-tail.unchk_fail_pre.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-tail.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-attributes-tail.unchk_pass.stderr b/tests/ui/contracts/contract-attributes-tail.unchk_pass.stderr
new file mode 100644
index 0000000000000..f87e7e19fa3db
--- /dev/null
+++ b/tests/ui/contracts/contract-attributes-tail.unchk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-attributes-tail.rs:19:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-captures-via-closure-copy.rs b/tests/ui/contracts/contract-captures-via-closure-copy.rs
new file mode 100644
index 0000000000000..32c6d2bf4fe17
--- /dev/null
+++ b/tests/ui/contracts/contract-captures-via-closure-copy.rs
@@ -0,0 +1,26 @@
+//@ run-fail
+//@ compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+struct Baz {
+    baz: i32
+}
+
+#[track_caller]
+#[core::contracts::requires(x.baz > 0)]
+#[core::contracts::ensures({let old = x.baz; move |ret:&Baz| ret.baz == old*2 })]
+// Relevant thing is this:  ^^^^^^^^^^^^^^^
+// because we are capturing state that is Copy
+fn doubler(x: Baz) -> Baz {
+    Baz { baz: x.baz + 10 }
+}
+
+fn main() {
+    assert_eq!(doubler(Baz { baz: 10 }).baz, 20);
+    assert_eq!(doubler(Baz { baz: 100 }).baz, 200);
+    // This is a *run-fail* test because it is still exercising the
+    // contract machinery, specifically because this second invocation
+    // of `doubler` shows how the code does not meet its contract.
+}
diff --git a/tests/ui/contracts/contract-captures-via-closure-copy.stderr b/tests/ui/contracts/contract-captures-via-closure-copy.stderr
new file mode 100644
index 0000000000000..d92db601608f5
--- /dev/null
+++ b/tests/ui/contracts/contract-captures-via-closure-copy.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-captures-via-closure-copy.rs:4:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contract-captures-via-closure-noncopy.rs b/tests/ui/contracts/contract-captures-via-closure-noncopy.rs
new file mode 100644
index 0000000000000..976f64c7fd911
--- /dev/null
+++ b/tests/ui/contracts/contract-captures-via-closure-noncopy.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+struct Baz {
+    baz: i32
+}
+
+#[track_caller]
+#[core::contracts::requires(x.baz > 0)]
+#[core::contracts::ensures({let old = x; move |ret:&Baz| ret.baz == old.baz*2 })]
+// Relevant thing is this:  ^^^^^^^^^^^
+// because we are capturing state that is non-Copy.
+//~^^^ ERROR trait bound `Baz: std::marker::Copy` is not satisfied
+fn doubler(x: Baz) -> Baz {
+    Baz { baz: x.baz + 10 }
+}
+
+fn main() {
+    assert_eq!(doubler(Baz { baz: 10 }).baz, 20);
+    assert_eq!(doubler(Baz { baz: 100 }).baz, 200);
+}
diff --git a/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr
new file mode 100644
index 0000000000000..4a47671fee191
--- /dev/null
+++ b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr
@@ -0,0 +1,36 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-captures-via-closure-noncopy.rs:3:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `Baz: std::marker::Copy` is not satisfied in `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}`
+  --> $DIR/contract-captures-via-closure-noncopy.rs:12:1
+   |
+LL | #[core::contracts::ensures({let old = x; move |ret:&Baz| ret.baz == old.baz*2 })]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^^
+   | |                                        |
+   | |                                        within this `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}`
+   | |                                        this tail expression is of type `{closure@contract-captures-via-closure-noncopy.rs:12:42}`
+   | unsatisfied trait bound
+   |
+   = help: within `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}`, the trait `std::marker::Copy` is not implemented for `Baz`
+note: required because it's used within this closure
+  --> $DIR/contract-captures-via-closure-noncopy.rs:12:42
+   |
+LL | #[core::contracts::ensures({let old = x; move |ret:&Baz| ret.baz == old.baz*2 })]
+   |                                          ^^^^^^^^^^^^^^^
+note: required by a bound in `build_check_ensures`
+  --> $SRC_DIR/core/src/contracts.rs:LL:COL
+help: consider annotating `Baz` with `#[derive(Copy)]`
+   |
+LL + #[derive(Copy)]
+LL | struct Baz {
+   |
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_ret.stderr b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_ret.stderr
new file mode 100644
index 0000000000000..d693fad446a4d
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_ret.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contracts-ensures-early-fn-exit.rs:16:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_try.stderr b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_try.stderr
new file mode 100644
index 0000000000000..d693fad446a4d
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_try.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contracts-ensures-early-fn-exit.rs:16:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_yeet.stderr b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_yeet.stderr
new file mode 100644
index 0000000000000..d693fad446a4d
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_fail_yeet.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contracts-ensures-early-fn-exit.rs:16:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_pass.stderr b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_pass.stderr
new file mode 100644
index 0000000000000..d693fad446a4d
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.chk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contracts-ensures-early-fn-exit.rs:16:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.rs b/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
new file mode 100644
index 0000000000000..034cead3b4e9f
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
@@ -0,0 +1,49 @@
+//@ revisions: unchk_pass chk_pass chk_fail_try chk_fail_ret chk_fail_yeet
+//
+//@ [unchk_pass] run-pass
+//@ [chk_pass] run-pass
+//@ [chk_fail_try] run-fail
+//@ [chk_fail_ret] run-fail
+//@ [chk_fail_yeet] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_try] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_ret] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_yeet] compile-flags: -Zcontract-checks=yes
+//! This test ensures that ensures clauses are checked for different return points of a function.
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+#![feature(yeet_expr)]
+
+/// This ensures will fail in different return points depending on the input.
+#[core::contracts::ensures(|ret: &Option<u32>| ret.is_some())]
+fn try_sum(x: u32, y: u32, z: u32) -> Option<u32> {
+    // Use Yeet to return early.
+    if x == u32::MAX && (y > 0 || z > 0) { do yeet }
+
+    // Use `?` to early return.
+    let partial = x.checked_add(y)?;
+
+    // Explicitly use `return` clause.
+    if u32::MAX - partial < z {
+        return None;
+    }
+
+    Some(partial + z)
+}
+
+fn main() {
+    // This should always succeed
+    assert_eq!(try_sum(0, 1, 2), Some(3));
+
+    #[cfg(any(unchk_pass, chk_fail_yeet))]
+    assert_eq!(try_sum(u32::MAX, 1, 1), None);
+
+    #[cfg(any(unchk_pass, chk_fail_try))]
+    assert_eq!(try_sum(u32::MAX - 10, 12, 0), None);
+
+    #[cfg(any(unchk_pass, chk_fail_ret))]
+    assert_eq!(try_sum(u32::MAX - 10, 2, 100), None);
+}
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.unchk_pass.stderr b/tests/ui/contracts/contracts-ensures-early-fn-exit.unchk_pass.stderr
new file mode 100644
index 0000000000000..d693fad446a4d
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.unchk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contracts-ensures-early-fn-exit.rs:16:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contracts-ensures-is-not-inherited-when-nesting.rs b/tests/ui/contracts/contracts-ensures-is-not-inherited-when-nesting.rs
new file mode 100644
index 0000000000000..f01a852fbff34
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-is-not-inherited-when-nesting.rs
@@ -0,0 +1,15 @@
+//@ run-pass
+//@ compile-flags: -Zcontract-checks=yes
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+#[core::contracts::ensures(|ret| *ret > 0)]
+fn outer() -> i32 {
+    let inner_closure = || -> i32 { 0 };
+    inner_closure();
+    10
+}
+
+fn main() {
+    outer();
+}
diff --git a/tests/ui/contracts/contracts-ensures-is-not-inherited-when-nesting.stderr b/tests/ui/contracts/contracts-ensures-is-not-inherited-when-nesting.stderr
new file mode 100644
index 0000000000000..49a372b53c7d8
--- /dev/null
+++ b/tests/ui/contracts/contracts-ensures-is-not-inherited-when-nesting.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contracts-ensures-is-not-inherited-when-nesting.rs:3:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/contracts-requires-is-not-inherited-when-nesting.rs b/tests/ui/contracts/contracts-requires-is-not-inherited-when-nesting.rs
new file mode 100644
index 0000000000000..2c2a4a6978550
--- /dev/null
+++ b/tests/ui/contracts/contracts-requires-is-not-inherited-when-nesting.rs
@@ -0,0 +1,17 @@
+//@ run-pass
+//@ compile-flags: -Zcontract-checks=yes
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+
+struct Outer { outer: std::cell::Cell<i32> }
+
+#[core::contracts::requires(x.outer.get() > 0)]
+fn outer(x: Outer) {
+    let inner_closure = || { };
+    x.outer.set(0);
+    inner_closure();
+}
+
+fn main() {
+    outer(Outer { outer: 1.into() });
+}
diff --git a/tests/ui/contracts/contracts-requires-is-not-inherited-when-nesting.stderr b/tests/ui/contracts/contracts-requires-is-not-inherited-when-nesting.stderr
new file mode 100644
index 0000000000000..48898c4434ad5
--- /dev/null
+++ b/tests/ui/contracts/contracts-requires-is-not-inherited-when-nesting.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contracts-requires-is-not-inherited-when-nesting.rs:3:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/disallow-contract-annotation-on-non-fn.rs b/tests/ui/contracts/disallow-contract-annotation-on-non-fn.rs
new file mode 100644
index 0000000000000..69be906782a67
--- /dev/null
+++ b/tests/ui/contracts/disallow-contract-annotation-on-non-fn.rs
@@ -0,0 +1,53 @@
+//! Checks for compilation errors related to adding contracts to non-function items.
+
+#![feature(contracts)]
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+#![allow(dead_code)]
+
+#[core::contracts::requires(true)]
+//~^ ERROR contract annotations can only be used on functions
+struct Dummy(usize);
+
+#[core::contracts::ensures(|v| v == 100)]
+//~^ ERROR contract annotations can only be used on functions
+const MAX_VAL: usize = 100;
+
+// FIXME: Improve the error message here. The macro thinks this is a function.
+#[core::contracts::ensures(|v| v == 100)]
+//~^ ERROR contract annotations is only supported in functions with bodies
+type NewDummy = fn(usize) -> Dummy;
+
+#[core::contracts::ensures(|v| v == 100)]
+//~^ ERROR contract annotations is only supported in functions with bodies
+const NEW_DUMMY_FN : fn(usize) -> Dummy = || { Dummy(0) };
+
+#[core::contracts::requires(true)]
+//~^ ERROR contract annotations can only be used on functions
+impl Dummy {
+
+    // This should work
+    #[core::contracts::ensures(|ret| ret.0 == v)]
+    fn new(v: usize) -> Dummy {
+        Dummy(v)
+    }
+}
+
+#[core::contracts::ensures(|dummy| dummy.0 > 0)]
+//~^ ERROR contract annotations can only be used on functions
+impl From<usize> for Dummy {
+    // This should work.
+    #[core::contracts::ensures(|ret| ret.0 == v)]
+    fn from(value: usize) -> Self {
+        Dummy::new(value)
+    }
+}
+
+/// You should not be able to annotate a trait either.
+#[core::contracts::requires(true)]
+//~^ ERROR contract annotations can only be used on functions
+pub trait DummyBuilder {
+    fn build() -> Dummy;
+}
+
+fn main() {
+}
diff --git a/tests/ui/contracts/disallow-contract-annotation-on-non-fn.stderr b/tests/ui/contracts/disallow-contract-annotation-on-non-fn.stderr
new file mode 100644
index 0000000000000..0a7fff8183e09
--- /dev/null
+++ b/tests/ui/contracts/disallow-contract-annotation-on-non-fn.stderr
@@ -0,0 +1,53 @@
+error: contract annotations can only be used on functions
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:7:1
+   |
+LL | #[core::contracts::requires(true)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: contract annotations can only be used on functions
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:11:1
+   |
+LL | #[core::contracts::ensures(|v| v == 100)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: contract annotations is only supported in functions with bodies
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:16:1
+   |
+LL | #[core::contracts::ensures(|v| v == 100)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: contract annotations is only supported in functions with bodies
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:20:1
+   |
+LL | #[core::contracts::ensures(|v| v == 100)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: contract annotations can only be used on functions
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:24:1
+   |
+LL | #[core::contracts::requires(true)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: contract annotations can only be used on functions
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:35:1
+   |
+LL | #[core::contracts::ensures(|dummy| dummy.0 > 0)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: contract annotations can only be used on functions
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:46:1
+   |
+LL | #[core::contracts::requires(true)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/disallow-contract-annotation-on-non-fn.rs:3:12
+   |
+LL | #![feature(contracts)]
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 7 previous errors; 1 warning emitted
+
diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
new file mode 100644
index 0000000000000..6d8cd3949eedb
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
@@ -0,0 +1,44 @@
+//@ revisions: unchk_pass unchk_fail_pre unchk_fail_post chk_pass chk_fail_pre chk_fail_post
+//
+//@ [unchk_pass] run-pass
+//@ [unchk_fail_pre] run-pass
+//@ [unchk_fail_post] run-pass
+//@ [chk_pass] run-pass
+//
+//@ [chk_fail_pre] run-fail
+//@ [chk_fail_post] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_post] compile-flags: -Zcontract-checks=no
+//
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_post] compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts_internals)]
+
+fn nest(x: Baz) -> i32
+    contract_requires(|| x.baz > 0)
+    contract_ensures(|ret| *ret > 100)
+{
+    loop {
+        return x.baz + 50;
+    }
+}
+
+struct Baz { baz: i32 }
+
+const BAZ_PASS_PRE_POST: Baz = Baz { baz: 100 };
+#[cfg(any(unchk_fail_post, chk_fail_post))]
+const BAZ_FAIL_POST: Baz = Baz { baz: 10 };
+#[cfg(any(unchk_fail_pre, chk_fail_pre))]
+const BAZ_FAIL_PRE: Baz = Baz { baz: -10 };
+
+fn main() {
+    assert_eq!(nest(BAZ_PASS_PRE_POST), 150);
+    #[cfg(any(unchk_fail_pre, chk_fail_pre))]
+    nest(BAZ_FAIL_PRE);
+    #[cfg(any(unchk_fail_post, chk_fail_post))]
+    nest(BAZ_FAIL_POST);
+}
diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
new file mode 100644
index 0000000000000..07ec26f921b80
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
@@ -0,0 +1,42 @@
+//@ revisions: unchk_pass unchk_fail_pre unchk_fail_post chk_pass chk_fail_pre chk_fail_post
+//
+//@ [unchk_pass] run-pass
+//@ [unchk_fail_pre] run-pass
+//@ [unchk_fail_post] run-pass
+//@ [chk_pass] run-pass
+//
+//@ [chk_fail_pre] run-fail
+//@ [chk_fail_post] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_post] compile-flags: -Zcontract-checks=no
+//
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_post] compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts_internals)]
+
+fn tail(x: Baz) -> i32
+    contract_requires(|| x.baz > 0)
+    contract_ensures(|ret| *ret > 100)
+{
+    x.baz + 50
+}
+
+struct Baz { baz: i32 }
+
+const BAZ_PASS_PRE_POST: Baz = Baz { baz: 100 };
+#[cfg(any(unchk_fail_post, chk_fail_post))]
+const BAZ_FAIL_POST: Baz = Baz { baz: 10 };
+#[cfg(any(unchk_fail_pre, chk_fail_pre))]
+const BAZ_FAIL_PRE: Baz = Baz { baz: -10 };
+
+fn main() {
+    assert_eq!(tail(BAZ_PASS_PRE_POST), 150);
+    #[cfg(any(unchk_fail_pre, chk_fail_pre))]
+    tail(BAZ_FAIL_PRE);
+    #[cfg(any(unchk_fail_post, chk_fail_post))]
+    tail(BAZ_FAIL_POST);
+}
diff --git a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
new file mode 100644
index 0000000000000..ae692afd146fe
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
@@ -0,0 +1,36 @@
+//@ revisions: default unchk_pass chk_pass chk_fail_ensures chk_fail_requires
+//
+//@ [default] run-pass
+//@ [unchk_pass] run-pass
+//@ [chk_pass] run-pass
+//@ [chk_fail_requires] run-fail
+//@ [chk_fail_ensures] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_requires] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_ensures] compile-flags: -Zcontract-checks=yes
+#![feature(cfg_contract_checks, contracts_internals, core_intrinsics)]
+
+fn main() {
+    #[cfg(any(default, unchk_pass))] // default: disabled
+    assert_eq!(core::intrinsics::contract_checks(), false);
+
+    #[cfg(chk_pass)] // explicitly enabled
+    assert_eq!(core::intrinsics::contract_checks(), true);
+
+    // always pass
+    core::intrinsics::contract_check_requires(|| true);
+
+    // fail if enabled
+    #[cfg(any(default, unchk_pass, chk_fail_requires))]
+    core::intrinsics::contract_check_requires(|| false);
+
+    let doubles_to_two = { let old = 2; move |ret| ret + ret == old };
+    // Always pass
+    core::intrinsics::contract_check_ensures(&1, doubles_to_two);
+
+    // Fail if enabled
+    #[cfg(any(default, unchk_pass, chk_fail_ensures))]
+    core::intrinsics::contract_check_ensures(&2, doubles_to_two);
+}
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.chk_fail_post.stderr b/tests/ui/contracts/internal_machinery/contract-lang-items.chk_fail_post.stderr
new file mode 100644
index 0000000000000..a60ce1602659b
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.chk_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-lang-items.rs:15:12
+   |
+LL | #![feature(contracts)] // to access core::contracts
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.chk_pass.stderr b/tests/ui/contracts/internal_machinery/contract-lang-items.chk_pass.stderr
new file mode 100644
index 0000000000000..a60ce1602659b
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.chk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-lang-items.rs:15:12
+   |
+LL | #![feature(contracts)] // to access core::contracts
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.rs b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
new file mode 100644
index 0000000000000..e91bbed294d12
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
@@ -0,0 +1,39 @@
+//@ revisions: unchk_pass unchk_fail_post chk_pass chk_fail_post
+//
+//@ [unchk_pass] run-pass
+//@ [unchk_fail_post] run-pass
+//@ [chk_pass] run-pass
+//
+//@ [chk_fail_post] run-fail
+//
+//@ [unchk_pass] compile-flags: -Zcontract-checks=no
+//@ [unchk_fail_post] compile-flags: -Zcontract-checks=no
+//
+//@ [chk_pass] compile-flags: -Zcontract-checks=yes
+//@ [chk_fail_post] compile-flags: -Zcontract-checks=yes
+
+#![feature(contracts)] // to access core::contracts
+//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
+#![feature(contracts_internals)] // to access check_requires lang item
+
+fn foo(x: Baz) -> i32 {
+    let injected_checker = {
+        core::contracts::build_check_ensures(|ret| *ret > 100)
+    };
+
+    let ret = x.baz + 50;
+    injected_checker(ret)
+}
+
+struct Baz { baz: i32 }
+
+
+const BAZ_PASS_PRE_POST: Baz = Baz { baz: 100 };
+#[cfg(any(unchk_fail_post, chk_fail_post))]
+const BAZ_FAIL_POST: Baz = Baz { baz: 10 };
+
+fn main() {
+    assert_eq!(foo(BAZ_PASS_PRE_POST), 150);
+    #[cfg(any(unchk_fail_post, chk_fail_post))]
+    foo(BAZ_FAIL_POST);
+}
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.unchk_fail_post.stderr b/tests/ui/contracts/internal_machinery/contract-lang-items.unchk_fail_post.stderr
new file mode 100644
index 0000000000000..a60ce1602659b
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.unchk_fail_post.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-lang-items.rs:15:12
+   |
+LL | #![feature(contracts)] // to access core::contracts
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.unchk_pass.stderr b/tests/ui/contracts/internal_machinery/contract-lang-items.unchk_pass.stderr
new file mode 100644
index 0000000000000..a60ce1602659b
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.unchk_pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/contract-lang-items.rs:15:12
+   |
+LL | #![feature(contracts)] // to access core::contracts
+   |            ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/contracts/internal_machinery/contracts-lowering-ensures-is-not-inherited-when-nesting.rs b/tests/ui/contracts/internal_machinery/contracts-lowering-ensures-is-not-inherited-when-nesting.rs
new file mode 100644
index 0000000000000..960ccaed3588a
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contracts-lowering-ensures-is-not-inherited-when-nesting.rs
@@ -0,0 +1,15 @@
+//@ run-pass
+//@ compile-flags: -Zcontract-checks=yes
+#![feature(contracts_internals)]
+
+fn outer() -> i32
+    contract_ensures(|ret| *ret > 0)
+{
+    let inner_closure = || -> i32 { 0 };
+    inner_closure();
+    10
+}
+
+fn main() {
+    outer();
+}
diff --git a/tests/ui/contracts/internal_machinery/contracts-lowering-requires-is-not-inherited-when-nesting.rs b/tests/ui/contracts/internal_machinery/contracts-lowering-requires-is-not-inherited-when-nesting.rs
new file mode 100644
index 0000000000000..bee703de16a0b
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/contracts-lowering-requires-is-not-inherited-when-nesting.rs
@@ -0,0 +1,17 @@
+//@ run-pass
+//@ compile-flags: -Zcontract-checks=yes
+#![feature(contracts_internals)]
+
+struct Outer { outer: std::cell::Cell<i32> }
+
+fn outer(x: Outer)
+    contract_requires(|| x.outer.get() > 0)
+{
+    let inner_closure = || { };
+    x.outer.set(0);
+    inner_closure();
+}
+
+fn main() {
+    outer(Outer { outer: 1.into() });
+}
diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.rs b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs
new file mode 100644
index 0000000000000..1b76eef6780fe
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs
@@ -0,0 +1,20 @@
+// gate-test-contracts_internals
+
+fn main() {
+    // intrinsics are guarded by contracts_internals feature gate.
+    core::intrinsics::contract_checks();
+    //~^ ERROR use of unstable library feature `contracts_internals`
+    core::intrinsics::contract_check_requires(|| true);
+    //~^ ERROR use of unstable library feature `contracts_internals`
+    core::intrinsics::contract_check_ensures(&1, |_|true);
+    //~^ ERROR use of unstable library feature `contracts_internals`
+
+    core::contracts::build_check_ensures(|_: &()| true);
+    //~^ ERROR use of unstable library feature `contracts_internals`
+
+    // ast extensions are guarded by contracts_internals feature gate
+    fn identity_1() -> i32 contract_requires(|| true) { 10 }
+    //~^ ERROR contract internal machinery is for internal use only
+    fn identity_2() -> i32 contract_ensures(|_| true) { 10 }
+    //~^ ERROR contract internal machinery is for internal use only
+}
diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr
new file mode 100644
index 0000000000000..c0e1522f54c61
--- /dev/null
+++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr
@@ -0,0 +1,63 @@
+error[E0658]: contract internal machinery is for internal use only
+  --> $DIR/internal-feature-gating.rs:16:45
+   |
+LL |     fn identity_1() -> i32 contract_requires(|| true) { 10 }
+   |                                             ^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts_internals)]` 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]: contract internal machinery is for internal use only
+  --> $DIR/internal-feature-gating.rs:18:44
+   |
+LL |     fn identity_2() -> i32 contract_ensures(|_| true) { 10 }
+   |                                            ^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts_internals)]` 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]: use of unstable library feature `contracts_internals`
+  --> $DIR/internal-feature-gating.rs:5:5
+   |
+LL |     core::intrinsics::contract_checks();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts_internals)]` 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]: use of unstable library feature `contracts_internals`
+  --> $DIR/internal-feature-gating.rs:7:5
+   |
+LL |     core::intrinsics::contract_check_requires(|| true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts_internals)]` 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]: use of unstable library feature `contracts_internals`
+  --> $DIR/internal-feature-gating.rs:9:5
+   |
+LL |     core::intrinsics::contract_check_ensures(&1, |_|true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts_internals)]` 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]: use of unstable library feature `contracts_internals`
+  --> $DIR/internal-feature-gating.rs:12:5
+   |
+LL |     core::contracts::build_check_ensures(|_: &()| true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts_internals)]` 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 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/editions/auxiliary/nested_macro_rules_dep_2021.rs b/tests/ui/editions/auxiliary/nested_macro_rules_dep_2021.rs
new file mode 100644
index 0000000000000..36d3e712dc0e9
--- /dev/null
+++ b/tests/ui/editions/auxiliary/nested_macro_rules_dep_2021.rs
@@ -0,0 +1,23 @@
+//@ edition: 2021
+
+#[macro_export]
+macro_rules! make_macro_with_input {
+    ($i:ident) => {
+        macro_rules! macro_inner_input {
+            () => {
+                pub fn $i() {}
+            };
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! make_macro {
+    () => {
+        macro_rules! macro_inner {
+            () => {
+                pub fn gen() {}
+            };
+        }
+    };
+}
diff --git a/tests/ui/editions/auxiliary/nested_macro_rules_dep_2024.rs b/tests/ui/editions/auxiliary/nested_macro_rules_dep_2024.rs
new file mode 100644
index 0000000000000..4012398fe6622
--- /dev/null
+++ b/tests/ui/editions/auxiliary/nested_macro_rules_dep_2024.rs
@@ -0,0 +1,23 @@
+//@ edition: 2024
+
+#[macro_export]
+macro_rules! make_macro_with_input {
+    ($i:ident) => {
+        macro_rules! macro_inner_input {
+            () => {
+                pub fn $i() {}
+            };
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! make_macro {
+    () => {
+        macro_rules! macro_inner {
+            () => {
+                pub fn gen() {}
+            };
+        }
+    };
+}
diff --git a/tests/ui/editions/nested-macro-rules-edition.e2021.stderr b/tests/ui/editions/nested-macro-rules-edition.e2021.stderr
new file mode 100644
index 0000000000000..eac80262364ba
--- /dev/null
+++ b/tests/ui/editions/nested-macro-rules-edition.e2021.stderr
@@ -0,0 +1,27 @@
+error: expected identifier, found reserved keyword `gen`
+  --> $DIR/nested-macro-rules-edition.rs:30:5
+   |
+LL |     macro_inner_input!{}
+   |     ^^^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
+   |
+   = note: this error originates in the macro `macro_inner_input` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: escape `gen` to use it as an identifier
+   |
+LL |     nested_macro_rules_dep::make_macro_with_input!{r#gen}
+   |                                                    ++
+
+error: expected identifier, found reserved keyword `gen`
+  --> $DIR/nested-macro-rules-edition.rs:35:5
+   |
+LL |     macro_inner!{}
+   |     ^^^^^^^^^^^^^^ expected identifier, found reserved keyword
+   |
+   = note: this error originates in the macro `macro_inner` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: escape `gen` to use it as an identifier
+  --> $DIR/auxiliary/nested_macro_rules_dep_2024.rs:19:24
+   |
+LL |                 pub fn r#gen() {}
+   |                        ++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/editions/nested-macro-rules-edition.rs b/tests/ui/editions/nested-macro-rules-edition.rs
new file mode 100644
index 0000000000000..28d568f77501b
--- /dev/null
+++ b/tests/ui/editions/nested-macro-rules-edition.rs
@@ -0,0 +1,39 @@
+// This checks the behavior of how nested macro_rules definitions are handled
+// with regards to edition spans. Prior to https://github.com/rust-lang/rust/pull/133274,
+// the compiler would compile the inner macro with the edition of the local crate.
+// Afterwards, it uses the edition where the macro was *defined*.
+//
+// Unfortunately macro_rules compiler discards the edition of any *input* that
+// was used to generate the macro. This is possibly not the behavior that we
+// want. If we want to keep with the philosophy that code should follow the
+// edition rules of the crate where it is written, then presumably we would
+// want the input tokens to retain the edition of where they were written.
+//
+// See https://github.com/rust-lang/rust/issues/135669 for more.
+//
+// This has two revisions, one where local=2021 and the dep=2024. The other
+// revision is vice-versa.
+
+//@ revisions: e2021 e2024
+//@[e2021] edition:2021
+//@[e2024] edition:2024
+//@[e2021] aux-crate: nested_macro_rules_dep=nested_macro_rules_dep_2024.rs
+//@[e2024] aux-crate: nested_macro_rules_dep=nested_macro_rules_dep_2021.rs
+//@[e2024] check-pass
+
+mod with_input {
+    // If we change the macro_rules input behavior, then this should pass when
+    // local edition is 2021 because `gen` is written in a context with 2021
+    // behavior. For local edition 2024, the reverse would be true and this
+    // should fail.
+    nested_macro_rules_dep::make_macro_with_input!{gen}
+    macro_inner_input!{}
+    //[e2021]~^ ERROR found reserved keyword
+}
+mod no_input {
+    nested_macro_rules_dep::make_macro!{}
+    macro_inner!{}
+    //[e2021]~^ ERROR found reserved keyword
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-contract-checks.rs b/tests/ui/feature-gates/feature-gate-cfg-contract-checks.rs
new file mode 100644
index 0000000000000..cd9bf12b5e773
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-contract-checks.rs
@@ -0,0 +1,5 @@
+#![crate_type = "lib"]
+
+pub fn contract_checks_are_enabled() -> bool {
+    cfg!(contract_checks) //~ ERROR `cfg(contract_checks)` is experimental
+}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-contract-checks.stderr b/tests/ui/feature-gates/feature-gate-cfg-contract-checks.stderr
new file mode 100644
index 0000000000000..89c6d077f97eb
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-contract-checks.stderr
@@ -0,0 +1,13 @@
+error[E0658]: `cfg(contract_checks)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-contract-checks.rs:4:10
+   |
+LL |     cfg!(contract_checks)
+   |          ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(cfg_contract_checks)]` 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 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-contracts.rs b/tests/ui/feature-gates/feature-gate-contracts.rs
new file mode 100644
index 0000000000000..5544f1d82ee4c
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-contracts.rs
@@ -0,0 +1,11 @@
+#![crate_type = "lib"]
+
+#[core::contracts::requires(x > 0)]
+pub fn requires_needs_it(x: i32) { }
+//~^^  ERROR use of unstable library feature `contracts`
+//~^^^ ERROR contracts are incomplete
+
+#[core::contracts::ensures(|ret| *ret > 0)]
+pub fn ensures_needs_it() -> i32 { 10 }
+//~^^  ERROR use of unstable library feature `contracts`
+//~^^^ ERROR contracts are incomplete
diff --git a/tests/ui/feature-gates/feature-gate-contracts.stderr b/tests/ui/feature-gates/feature-gate-contracts.stderr
new file mode 100644
index 0000000000000..4403e7df50b49
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-contracts.stderr
@@ -0,0 +1,43 @@
+error[E0658]: use of unstable library feature `contracts`
+  --> $DIR/feature-gate-contracts.rs:3:3
+   |
+LL | #[core::contracts::requires(x > 0)]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts)]` 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]: use of unstable library feature `contracts`
+  --> $DIR/feature-gate-contracts.rs:8:3
+   |
+LL | #[core::contracts::ensures(|ret| *ret > 0)]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts)]` 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]: contracts are incomplete
+  --> $DIR/feature-gate-contracts.rs:3:1
+   |
+LL | #[core::contracts::requires(x > 0)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts)]` 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]: contracts are incomplete
+  --> $DIR/feature-gate-contracts.rs:8:1
+   |
+LL | #[core::contracts::ensures(|ret| *ret > 0)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
+   = help: add `#![feature(contracts)]` 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 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/fn/error-recovery-mismatch.rs b/tests/ui/fn/error-recovery-mismatch.rs
new file mode 100644
index 0000000000000..a50a30c8c78a6
--- /dev/null
+++ b/tests/ui/fn/error-recovery-mismatch.rs
@@ -0,0 +1,20 @@
+// Used to ICE due to a size mismatch between the actual fake signature of `fold` and the
+// generated signature used reporting the parameter mismatch at the call site.
+// See issue #135124
+
+trait A  {
+    fn y(&self)
+    {
+        fn call() -> impl Sized {}
+        self.fold(call(), call());
+    }
+    fn fold<T>(&self, _: T, &self._) {}
+    //~^ ERROR unexpected `self` parameter in function
+    //~| ERROR expected one of `)` or `,`, found `.`
+    //~| ERROR identifier `self` is bound more than once in this parameter list
+    //~| WARNING anonymous parameters are deprecated
+    //~| WARNING this is accepted in the current edition
+    //~| ERROR the placeholder `_` is not allowed within types
+}
+
+fn main() {}
diff --git a/tests/ui/fn/error-recovery-mismatch.stderr b/tests/ui/fn/error-recovery-mismatch.stderr
new file mode 100644
index 0000000000000..ad4652c11c12f
--- /dev/null
+++ b/tests/ui/fn/error-recovery-mismatch.stderr
@@ -0,0 +1,46 @@
+error: unexpected `self` parameter in function
+  --> $DIR/error-recovery-mismatch.rs:11:29
+   |
+LL |     fn fold<T>(&self, _: T, &self._) {}
+   |                             ^^^^^ must be the first parameter of an associated function
+
+error: expected one of `)` or `,`, found `.`
+  --> $DIR/error-recovery-mismatch.rs:11:34
+   |
+LL |     fn fold<T>(&self, _: T, &self._) {}
+   |                                  ^
+   |                                  |
+   |                                  expected one of `)` or `,`
+   |                                  help: missing `,`
+
+error[E0415]: identifier `self` is bound more than once in this parameter list
+  --> $DIR/error-recovery-mismatch.rs:11:30
+   |
+LL |     fn fold<T>(&self, _: T, &self._) {}
+   |                              ^^^^ used as parameter more than once
+
+warning: anonymous parameters are deprecated and will be removed in the next edition
+  --> $DIR/error-recovery-mismatch.rs:11:35
+   |
+LL |     fn fold<T>(&self, _: T, &self._) {}
+   |                                   ^ help: try naming the parameter or explicitly ignoring it: `_: _`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+   = note: `#[warn(anonymous_parameters)]` on by default
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/error-recovery-mismatch.rs:11:35
+   |
+LL |     fn fold<T>(&self, _: T, &self._) {}
+   |                                   ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |     fn fold<T, U>(&self, _: T, &self.U) {}
+   |              +++                     ~
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0121, E0415.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/fn/param-mismatch-trait-fn.rs b/tests/ui/fn/param-mismatch-trait-fn.rs
new file mode 100644
index 0000000000000..69ded6a9068d7
--- /dev/null
+++ b/tests/ui/fn/param-mismatch-trait-fn.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    fn same_type<T>(_: T, _: T);
+}
+
+fn f<T: Foo, X, Y>(x: X, y: Y) {
+    T::same_type([x], Some(y));
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/fn/param-mismatch-trait-fn.stderr b/tests/ui/fn/param-mismatch-trait-fn.stderr
new file mode 100644
index 0000000000000..28e1bcaaf49dc
--- /dev/null
+++ b/tests/ui/fn/param-mismatch-trait-fn.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+  --> $DIR/param-mismatch-trait-fn.rs:6:23
+   |
+LL |     T::same_type([x], Some(y));
+   |     ------------ ---  ^^^^^^^ expected `[X; 1]`, found `Option<Y>`
+   |     |            |
+   |     |            expected all arguments to be this `[X; 1]` type because they need to match the type of this parameter
+   |     arguments to this function are incorrect
+   |
+   = note: expected array `[X; 1]`
+               found enum `Option<Y>`
+note: associated function defined here
+  --> $DIR/param-mismatch-trait-fn.rs:2:8
+   |
+LL |     fn same_type<T>(_: T, _: T);
+   |        ^^^^^^^^^ -  -     - this parameter needs to match the `[X; 1]` type of parameter #1
+   |                  |  |
+   |                  |  parameter #2 needs to match the `[X; 1]` type of this parameter
+   |                  parameter #1 and parameter #2 both reference this parameter `T`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr
index 35001ae22a6c7..7ac3d3dc0cff0 100644
--- a/tests/ui/methods/issues/issue-61525.stderr
+++ b/tests/ui/methods/issues/issue-61525.stderr
@@ -32,7 +32,7 @@ note: method defined here
   --> $DIR/issue-61525.rs:2:8
    |
 LL |     fn query<Q>(self, q: Q);
-   |        ^^^^^
+   |        ^^^^^          -
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
index 980c2455c8e41..df59a28c4b97b 100644
--- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
+++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
@@ -94,7 +94,7 @@ note: method defined here
   --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8
    |
 LL |     fn funk(&self, _: Self::A);
-   |        ^^^^
+   |        ^^^^        -
 help: consider constraining the associated type `<T as Trait<i32>>::A` to `{integer}`
    |
 LL | fn bar2<T: Trait<i32, A = {integer}>>(x: T) {
diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr
index c37dde90e336f..3c5df82fcdc87 100644
--- a/tests/ui/traits/issue-52893.stderr
+++ b/tests/ui/traits/issue-52893.stderr
@@ -22,7 +22,7 @@ note: method defined here
   --> $DIR/issue-52893.rs:11:8
    |
 LL |     fn push(self, other: T) -> Self::PushRes;
-   |        ^^^^
+   |        ^^^^       -----
 
 error: aborting due to 1 previous error