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 92492bfdb8d31..b727616ebceb9 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1650,6 +1650,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_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 1a216ebf117c6..5699d4ce3b9b6 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_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 09d7e60e19941..f53b4f3def259 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1103,6 +1103,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_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 b23cc90991154..529dfc6ff7a03 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/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/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/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/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`.