diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 937031324f57f..8a836951ff432 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3246,11 +3246,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: FnContract,
     pub body: Option<P<Block>>,
 }
 
@@ -3548,7 +3555,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, 176);
     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 1a7da46913d7e..471a459294776 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -119,6 +119,10 @@ pub trait MutVisitor: Sized {
         walk_flat_map_item(self, i)
     }
 
+    fn visit_contract(&mut self, c: &mut FnContract) {
+        walk_contract(self, c);
+    }
+
     fn visit_fn_decl(&mut self, d: &mut P<FnDecl>) {
         walk_fn_decl(self, d);
     }
@@ -898,6 +902,15 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
     }
 }
 
+fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut FnContract) {
+    if let Some(pred) = &mut contract.requires {
+        vis.visit_expr(pred);
+    }
+    if let Some(pred) = &mut contract.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));
@@ -1100,8 +1113,9 @@ impl WalkItemKind for ItemKind {
             ItemKind::Const(item) => {
                 visit_const_item(item, vis);
             }
-            ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            ItemKind::Fn(box Fn { defaultness, generics, sig, contract, body }) => {
                 visit_defaultness(vis, defaultness);
+                vis.visit_contract(contract);
                 vis.visit_fn(FnKind::Fn(sig, generics, body), span, id);
             }
             ItemKind::Mod(safety, mod_kind) => {
@@ -1206,8 +1220,9 @@ impl WalkItemKind for AssocItemKind {
             AssocItemKind::Const(item) => {
                 visit_const_item(item, visitor);
             }
-            AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            AssocItemKind::Fn(box Fn { defaultness, generics, sig, contract, body }) => {
                 visit_defaultness(visitor, defaultness);
+                visitor.visit_contract(contract);
                 visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id);
             }
             AssocItemKind::Type(box TyAlias {
@@ -1311,8 +1326,9 @@ impl WalkItemKind for ForeignItemKind {
                 visitor.visit_ty(ty);
                 visit_opt(expr, |expr| visitor.visit_expr(expr));
             }
-            ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+            ForeignItemKind::Fn(box Fn { defaultness, generics, sig, contract, body }) => {
                 visit_defaultness(visitor, defaultness);
+                visitor.visit_contract(contract);
                 visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id);
             }
             ForeignItemKind::TyAlias(box TyAlias {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 4dcadb8517eb4..dd30a7f1ce013 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -15,8 +15,8 @@
 
 pub use rustc_ast_ir::visit::VisitorResult;
 pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
-use rustc_span::Span;
 use rustc_span::symbol::Ident;
+use rustc_span::Span;
 
 use crate::ast::*;
 use crate::ptr::P;
@@ -66,7 +66,7 @@ impl BoundKind {
 #[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
-    Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
+    Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, &'a FnContract, Option<&'a Block>),
 
     /// E.g., `|x, y| body`.
     Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
@@ -75,7 +75,7 @@ pub enum FnKind<'a> {
 impl<'a> FnKind<'a> {
     pub fn header(&self) -> Option<&'a FnHeader> {
         match *self {
-            FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
+            FnKind::Fn(_, _, sig, _, _, _, _) => Some(&sig.header),
             FnKind::Closure(..) => None,
         }
     }
@@ -89,7 +89,7 @@ impl<'a> FnKind<'a> {
 
     pub fn decl(&self) -> &'a FnDecl {
         match self {
-            FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
+            FnKind::Fn(_, _, sig, _, _, _, _) => &sig.decl,
             FnKind::Closure(_, _, decl, _) => decl,
         }
     }
@@ -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)
     }
@@ -359,8 +362,16 @@ impl WalkItemKind for ItemKind {
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
             }
-            ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
-                let kind = FnKind::Fn(FnCtxt::Free, *ident, sig, vis, generics, body.as_deref());
+            ItemKind::Fn(box Fn { defaultness: _, generics, sig, contract, body }) => {
+                let kind = FnKind::Fn(
+                    FnCtxt::Free,
+                    *ident,
+                    sig,
+                    vis,
+                    generics,
+                    &contract,
+                    body.as_deref(),
+                );
                 try_visit!(visitor.visit_fn(kind, *span, *id));
             }
             ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
@@ -695,8 +706,16 @@ impl WalkItemKind for ForeignItemKind {
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
             }
-            ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
-                let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
+            ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, contract, body }) => {
+                let kind = FnKind::Fn(
+                    FnCtxt::Foreign,
+                    ident,
+                    sig,
+                    vis,
+                    generics,
+                    contract,
+                    body.as_deref(),
+                );
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             ForeignItemKind::TyAlias(box TyAlias {
@@ -784,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,
@@ -829,11 +859,20 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>(
 
 pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result {
     match kind {
-        FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) => {
+        FnKind::Fn(
+            _ctxt,
+            _ident,
+            FnSig { header, decl, span: _ },
+            _vis,
+            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!(walk_fn_decl(visitor, decl));
+            try_visit!(visitor.visit_contract(contract));
             visit_opt!(visitor, visit_block, body);
         }
         FnKind::Closure(binder, _coroutine_kind, decl, body) => {
@@ -859,9 +898,16 @@ impl WalkItemKind for AssocItemKind {
                 try_visit!(visitor.visit_ty(ty));
                 visit_opt!(visitor, visit_expr, expr);
             }
-            AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
-                let kind =
-                    FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
+            AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, contract, body }) => {
+                let kind = FnKind::Fn(
+                    FnCtxt::Assoc(ctxt),
+                    ident,
+                    sig,
+                    vis,
+                    generics,
+                    contract,
+                    body.as_deref(),
+                );
                 try_visit!(visitor.visit_fn(kind, span, id));
             }
             AssocItemKind::Type(box TyAlias {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 1273b50dff816..c9485aa565e57 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -3,17 +3,17 @@ use rustc_ast::visit::AssocCtxt;
 use rustc_ast::*;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
-use rustc_hir::PredicateOrigin;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::PredicateOrigin;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::symbol::{Ident, kw, sym};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{DesugaringKind, Span, Symbol};
 use rustc_target::spec::abi;
-use smallvec::{SmallVec, smallvec};
+use smallvec::{smallvec, SmallVec};
 use thin_vec::ThinVec;
 use tracing::instrument;
 
@@ -206,6 +206,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Fn(box Fn {
                 sig: FnSig { decl, header, span: fn_sig_span },
                 generics,
+                contract,
                 body,
                 ..
             }) => {
@@ -223,6 +224,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         coroutine_kind,
                         body.as_deref(),
                     );
+                    let last_recorded_body = this.bodies.last().unwrap();
+                    assert_eq!(last_recorded_body.0, body_id.hir_id.local_id);
+                    let contract_params: &'hir [hir::Param<'hir>] = last_recorded_body.1.params;
 
                     let itctx = ImplTraitContext::Universal;
                     let (generics, decl) =
@@ -240,7 +244,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         header: this.lower_fn_header(*header, hir::Safety::Safe),
                         span: this.lower_span(*fn_sig_span),
                     };
-                    hir::ItemKind::Fn(sig, generics, body_id)
+                    let contract_ids = this.lower_contract(id, contract_params, contract);
+                    hir::ItemKind::Fn(sig, generics, Some(contract_ids), body_id)
                 })
             }
             ItemKind::Mod(_, mod_kind) => match mod_kind {
@@ -281,12 +286,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             );
                             this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
                         }
-                        Some(ty) => this.lower_ty(ty, ImplTraitContext::OpaqueTy {
-                            origin: hir::OpaqueTyOrigin::TyAlias {
-                                parent: this.local_def_id(id),
-                                in_assoc_ty: false,
+                        Some(ty) => this.lower_ty(
+                            ty,
+                            ImplTraitContext::OpaqueTy {
+                                origin: hir::OpaqueTyOrigin::TyAlias {
+                                    parent: this.local_def_id(id),
+                                    in_assoc_ty: false,
+                                },
                             },
-                        }),
+                        ),
                     },
                 );
                 hir::ItemKind::TyAlias(ty, generics)
@@ -457,6 +465,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 hir::ItemKind::Fn(
                     delegation_results.sig,
                     delegation_results.generics,
+                    None,
                     delegation_results.body_id,
                 )
             }
@@ -977,12 +986,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             hir::ImplItemKind::Type(ty)
                         }
                         Some(ty) => {
-                            let ty = this.lower_ty(ty, ImplTraitContext::OpaqueTy {
-                                origin: hir::OpaqueTyOrigin::TyAlias {
-                                    parent: this.local_def_id(i.id),
-                                    in_assoc_ty: true,
+                            let ty = this.lower_ty(
+                                ty,
+                                ImplTraitContext::OpaqueTy {
+                                    origin: hir::OpaqueTyOrigin::TyAlias {
+                                        parent: this.local_def_id(i.id),
+                                        in_assoc_ty: true,
+                                    },
                                 },
-                            });
+                            );
                             hir::ImplItemKind::Type(ty)
                         }
                     },
@@ -1121,13 +1133,57 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
         self.lower_body(|this| {
-            (&[], match expr {
-                Some(expr) => this.lower_expr_mut(expr),
-                None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
-            })
+            (
+                &[],
+                match expr {
+                    Some(expr) => this.lower_expr_mut(expr),
+                    None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
+                },
+            )
         })
     }
 
+    fn lower_contract(
+        &mut self,
+        parent_node_id: NodeId,
+        params: &'hir [hir::Param<'hir>],
+        contract: &ast::FnContract,
+    ) -> &'hir hir::FnContractIds {
+        let precond: Option<&P<Expr>> = contract.requires.as_ref();
+        let postcond: Option<&P<Expr>> = contract.ensures.as_ref();
+        let precond: Option<hir::Contract> = precond.map(|e| {
+            let parent_node_hir_id = self.lower_node_id(parent_node_id);
+            let contract_node_id = self.next_node_id();
+
+            let def_id = self.create_def(
+                self.local_def_id(parent_node_id),
+                contract_node_id,
+                kw::Empty,
+                DefKind::Contract,
+                e.span,
+            );
+            self.children.push((def_id, hir::MaybeOwner::NonOwner(parent_node_hir_id)));
+            let body_id = self.lower_body(|this| (params, this.lower_expr_mut(e)));
+            hir::Contract { def_id, body_id }
+        });
+        let postcond: Option<hir::Contract> = postcond.map(|e| {
+            let parent_node_hir_id = self.lower_node_id(parent_node_id);
+            let contract_node_id = self.next_node_id();
+            let def_id = self.create_def(
+                self.local_def_id(parent_node_id),
+                contract_node_id,
+                kw::Empty,
+                DefKind::Contract,
+                e.span,
+            );
+            self.children.push((def_id, hir::MaybeOwner::NonOwner(parent_node_hir_id)));
+            let body_id = self.lower_body(|this| (params, this.lower_expr_mut(e)));
+            hir::Contract { def_id, body_id }
+        });
+
+        self.arena.alloc(hir::FnContractIds { precond, postcond })
+    }
+
     /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or
     /// `gen {}` block as appropriate.
     fn lower_maybe_coroutine_body(
@@ -1504,10 +1560,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
             for bound in &bound_pred.bounds {
                 if !matches!(
                     *bound,
-                    GenericBound::Trait(_, TraitBoundModifiers {
-                        polarity: BoundPolarity::Maybe(_),
-                        ..
-                    })
+                    GenericBound::Trait(
+                        _,
+                        TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }
+                    )
                 ) {
                     continue;
                 }
@@ -1608,13 +1664,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
             self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id)));
 
             let const_body = self.lower_body(|this| {
-                (&[], hir::Expr {
-                    hir_id: const_expr_id,
-                    kind: hir::ExprKind::Lit(
-                        this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }),
-                    ),
-                    span,
-                })
+                (
+                    &[],
+                    hir::Expr {
+                        hir_id: const_expr_id,
+                        kind: hir::ExprKind::Lit(
+                            this.arena.alloc(hir::Lit { node: LitKind::Bool(true), span }),
+                        ),
+                        span,
+                    },
+                )
             });
 
             let default_ac = self.arena.alloc(hir::AnonConst {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 365924ef782e8..bdf63bf3dec99 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -53,7 +53,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
+use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{
     self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName,
     TraitCandidate,
@@ -63,9 +63,9 @@ use rustc_macros::extension;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_session::parse::{add_feature_diagnostics, feature_err};
-use rustc_span::symbol::{Ident, Symbol, kw, sym};
-use rustc_span::{DUMMY_SP, DesugaringKind, Span};
-use smallvec::{SmallVec, smallvec};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{DesugaringKind, Span, DUMMY_SP};
+use smallvec::{smallvec, SmallVec};
 use thin_vec::ThinVec;
 use tracing::{debug, instrument, trace};
 
@@ -598,7 +598,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let current_attrs = std::mem::take(&mut self.attrs);
         let current_bodies = std::mem::take(&mut self.bodies);
         let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
-        let current_trait_map = std::mem::take(&mut self.trait_map);
+        let current_trait_map: rustc_data_structures::unord::UnordMap<
+            rustc_hir::ItemLocalId,
+            Box<[TraitCandidate]>,
+        > = std::mem::take(&mut self.trait_map);
         let current_owner =
             std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
         let current_local_counter =
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 87e3a6871b9e1..56b0572fb58e6 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -961,7 +961,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
             }
-            ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
+            ItemKind::Fn(box Fn { defaultness, sig, generics, contract, body }) => {
                 self.check_defaultness(item.span, *defaultness);
 
                 if body.is_none() {
@@ -989,8 +989,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
                 self.visit_vis(&item.vis);
                 self.visit_ident(item.ident);
+                // self.visit_contract(contract);
                 let kind =
-                    FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
+                    FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, contract, body.as_deref());
                 self.visit_fn(kind, item.span, item.id);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
@@ -1396,13 +1397,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             _,
             _,
             _,
+            _,
         ) = fk
         {
             self.maybe_lint_missing_abi(*sig_span, id);
         }
 
         // Functions without bodies cannot have patterns.
-        if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk {
+        if let FnKind::Fn(ctxt, _, sig, _, _, _, None) = fk {
             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
                     if let Some(ident) = ident {
@@ -1436,7 +1438,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .is_some();
 
         let disallowed = (!tilde_const_allowed).then(|| match fk {
-            FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span },
+            FnKind::Fn(_, ident, _, _, _, _, _) => TildeConstReason::Function { ident: ident.span },
             FnKind::Closure(..) => TildeConstReason::Closure,
         });
         self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
@@ -1512,7 +1514,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();
 
         match &item.kind {
-            AssocItemKind::Fn(box Fn { sig, generics, body, .. })
+            AssocItemKind::Fn(box Fn { sig, generics, contract, body, .. })
                 if parent_is_const
                     || ctxt == AssocCtxt::Trait
                     || matches!(sig.header.constness, Const::Yes(_)) =>
@@ -1525,6 +1527,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     sig,
                     &item.vis,
                     generics,
+                    contract,
                     body.as_deref(),
                 );
                 walk_list!(self, visit_attribute, &item.attrs);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 8217b6df5b470..41f7fba2c42f2 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -34,8 +34,8 @@ impl<'a> State<'a> {
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
-            ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
-                self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
+            ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, contract, body }) => {
+                self.print_fn_full(sig, ident, generics, vis, *defaultness, contract, body.as_deref(), attrs);
             }
             ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => {
                 self.print_safety(*safety);
@@ -195,13 +195,14 @@ impl<'a> State<'a> {
                     *defaultness,
                 );
             }
-            ast::ItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
+            ast::ItemKind::Fn(box ast::Fn { defaultness, sig, generics, contract, body }) => {
                 self.print_fn_full(
                     sig,
                     item.ident,
                     generics,
                     &item.vis,
                     *defaultness,
+                    contract,
                     body.as_deref(),
                     &item.attrs,
                 );
@@ -538,8 +539,8 @@ impl<'a> State<'a> {
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
-            ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
-                self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
+            ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, contract, body }) => {
+                self.print_fn_full(sig, ident, generics, vis, *defaultness, contract, body.as_deref(), attrs);
             }
             ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
                 self.print_item_const(
@@ -653,6 +654,7 @@ impl<'a> State<'a> {
         generics: &ast::Generics,
         vis: &ast::Visibility,
         defaultness: ast::Defaultness,
+        contract: &ast::FnContract,
         body: Option<&ast::Block>,
         attrs: &[ast::Attribute],
     ) {
@@ -662,6 +664,7 @@ impl<'a> State<'a> {
         self.print_visibility(vis);
         self.print_defaultness(defaultness);
         self.print_fn(&sig.decl, sig.header, Some(name), generics);
+        self.print_contract(contract);
         if let Some(body) = body {
             self.nbsp();
             self.print_block_with_attrs(body, attrs);
@@ -670,6 +673,17 @@ impl<'a> State<'a> {
         }
     }
 
+    fn print_contract(&mut self, contract: &ast::FnContract) {
+        if let Some(pred) = &contract.requires {
+            self.word("rustc_requires");
+            self.print_expr(pred, FixupContext::default());
+        }
+        if let Some(pred) = &contract.ensures {
+            self.word("rustc_ensures");
+            self.print_expr(pred, FixupContext::default());
+        }
+    }
+
     pub(crate) fn print_fn(
         &mut self,
         decl: &ast::FnDecl,
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index fa44ffcd17dd0..6a8327c43e16d 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -20,9 +20,9 @@ use std::iter;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Diag;
-use rustc_hir::BodyOwnerKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::BodyOwnerKind;
 use rustc_index::IndexVec;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_macros::extension;
@@ -37,8 +37,8 @@ use rustc_span::symbol::{kw, sym};
 use rustc_span::{ErrorGuaranteed, Symbol};
 use tracing::{debug, instrument};
 
-use crate::BorrowckInferCtxt;
 use crate::renumber::RegionCtxt;
+use crate::BorrowckInferCtxt;
 
 #[derive(Debug)]
 pub(crate) struct UniversalRegions<'tcx> {
@@ -98,6 +98,9 @@ pub(crate) struct UniversalRegions<'tcx> {
 /// appear bound in the signature.
 #[derive(Copy, Clone, Debug)]
 pub(crate) enum DefiningTy<'tcx> {
+    /// The MIR is a contract.
+    Contract(DefId, GenericArgsRef<'tcx>),
+
     /// The MIR is a closure. The signature is found via
     /// `ClosureArgs::closure_sig_ty`.
     Closure(DefId, GenericArgsRef<'tcx>),
@@ -138,9 +141,10 @@ impl<'tcx> DefiningTy<'tcx> {
             DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
             DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(),
             DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
-                ty::List::empty()
-            }
+            DefiningTy::Contract(..)
+            | DefiningTy::FnDef(..)
+            | DefiningTy::Const(..)
+            | DefiningTy::InlineConst(..) => ty::List::empty(),
         }
     }
 
@@ -152,6 +156,7 @@ impl<'tcx> DefiningTy<'tcx> {
             DefiningTy::Closure(..)
             | DefiningTy::CoroutineClosure(..)
             | DefiningTy::Coroutine(..) => 1,
+            DefiningTy::Contract(..) => 0, // FIXME: this should probably be a 0 for precond and 1 for postcond.
             DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
         }
     }
@@ -167,6 +172,7 @@ impl<'tcx> DefiningTy<'tcx> {
     pub(crate) fn def_id(&self) -> DefId {
         match *self {
             DefiningTy::Closure(def_id, ..)
+            | DefiningTy::Contract(def_id, ..)
             | DefiningTy::CoroutineClosure(def_id, ..)
             | DefiningTy::Coroutine(def_id, ..)
             | DefiningTy::FnDef(def_id, ..)
@@ -356,12 +362,10 @@ impl<'tcx> UniversalRegions<'tcx> {
     pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) {
         match self.defining_ty {
             DefiningTy::Closure(def_id, args) => {
-                let v = with_no_trimmed_paths!(
-                    args[tcx.generics_of(def_id).parent_count..]
-                        .iter()
-                        .map(|arg| arg.to_string())
-                        .collect::<Vec<_>>()
-                );
+                let v = with_no_trimmed_paths!(args[tcx.generics_of(def_id).parent_count..]
+                    .iter()
+                    .map(|arg| arg.to_string())
+                    .collect::<Vec<_>>());
                 err.note(format!(
                     "defining type: {} with closure args [\n    {},\n]",
                     tcx.def_path_str_with_args(def_id, args),
@@ -377,16 +381,14 @@ impl<'tcx> UniversalRegions<'tcx> {
                     err.note(format!("late-bound region is {:?}", self.to_region_vid(r)));
                 });
             }
-            DefiningTy::CoroutineClosure(..) => {
+            DefiningTy::Contract(..) | DefiningTy::CoroutineClosure(..) => {
                 todo!()
             }
             DefiningTy::Coroutine(def_id, args) => {
-                let v = with_no_trimmed_paths!(
-                    args[tcx.generics_of(def_id).parent_count..]
-                        .iter()
-                        .map(|arg| arg.to_string())
-                        .collect::<Vec<_>>()
-                );
+                let v = with_no_trimmed_paths!(args[tcx.generics_of(def_id).parent_count..]
+                    .iter()
+                    .map(|arg| arg.to_string())
+                    .collect::<Vec<_>>());
                 err.note(format!(
                     "defining type: {} with coroutine args [\n    {},\n]",
                     tcx.def_path_str_with_args(def_id, args),
@@ -629,15 +631,22 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     let ty = tcx
                         .typeck(self.mir_def)
                         .node_type(tcx.local_def_id_to_hir_id(self.mir_def));
-                    let args = InlineConstArgs::new(tcx, InlineConstArgsParts {
-                        parent_args: identity_args,
-                        ty,
-                    })
+                    let args = InlineConstArgs::new(
+                        tcx,
+                        InlineConstArgsParts { parent_args: identity_args, ty },
+                    )
                     .args;
                     let args = self.infcx.replace_free_regions_with_nll_infer_vars(FR, args);
                     DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
                 }
             }
+            BodyOwnerKind::Contract => {
+                let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id);
+                debug!("identity_args: {:?}", identity_args);
+                assert_eq!(self.mir_def.to_def_id(), typeck_root_def_id);
+                let args = self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args);
+                DefiningTy::Contract(self.mir_def.to_def_id(), args)
+            }
         }
     }
 
@@ -670,7 +679,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 args
             }
 
-            DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args,
+            DefiningTy::Contract(_, args)
+            | DefiningTy::FnDef(_, args)
+            | DefiningTy::Const(_, args) => args,
         };
 
         let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
@@ -789,6 +800,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 )
             }
 
+            DefiningTy::Contract(_def_id, _) => {
+                todo!()
+            }
+
             DefiningTy::FnDef(def_id, _) => {
                 let sig = tcx.fn_sig(def_id).instantiate_identity();
                 let sig = indices.fold_to_region_vids(tcx, sig);
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 0caad997b9df1..7830630ad5314 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -1,6 +1,7 @@
 use rustc_ast::ptr::P;
 use rustc_ast::{
-    self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind,
+    self as ast, Fn, FnContract, FnHeader, FnSig, Generics, ItemKind,
+    Safety, Stmt, StmtKind, TyKind,
 };
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::Span;
@@ -86,6 +87,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
         defaultness: ast::Defaultness::Final,
         sig,
         generics: Generics::default(),
+        contract: FnContract::default(),
         body,
     }));
 
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 82baaca9a4641..c095b321148f6 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1043,6 +1043,7 @@ impl<'a> MethodDef<'a> {
                 defaultness,
                 sig,
                 generics: fn_generics,
+                contract: ast::FnContract::default(),
                 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 b4b18409a18eb..59086e36d8a6a 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -82,6 +82,7 @@ impl AllocFnFactory<'_, '_> {
             defaultness: ast::Defaultness::Final,
             sig,
             generics: Generics::default(),
+            contract: ast::FnContract::default(),
             body,
         }));
         let item = self.cx.item(
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 953484533087c..24e460cda4279 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -346,6 +346,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
         defaultness,
         sig,
         generics: ast::Generics::default(),
+        contract: ast::FnContract::default(),
         body: Some(main_body),
     }));
 
diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs
index aaa95f6b7f19e..1ae34be4e7198 100644
--- a/compiler/rustc_data_structures/src/steal.rs
+++ b/compiler/rustc_data_structures/src/steal.rs
@@ -1,3 +1,5 @@
+use std::panic::Location;
+
 use crate::stable_hasher::{HashStable, StableHasher};
 use crate::sync::{MappedReadGuard, ReadGuard, RwLock};
 
@@ -24,18 +26,25 @@ use crate::sync::{MappedReadGuard, ReadGuard, RwLock};
 #[derive(Debug)]
 pub struct Steal<T> {
     value: RwLock<Option<T>>,
+    prev_stolen_by: RwLock<Option<&'static Location<'static>>>,
 }
 
 impl<T> Steal<T> {
     pub fn new(value: T) -> Self {
-        Steal { value: RwLock::new(Some(value)) }
+        Steal { value: RwLock::new(Some(value)), prev_stolen_by: RwLock::new(None) }
     }
 
     #[track_caller]
     pub fn borrow(&self) -> MappedReadGuard<'_, T> {
         let borrow = self.value.borrow();
         if borrow.is_none() {
-            panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
+            panic!(
+                "attempted to read from stolen value: {}, last stolen by: {}",
+                std::any::type_name::<T>(),
+                self.prev_stolen_by
+                    .read()
+                    .expect("if its stolen then prev_stolen_by should be set"),
+            );
         }
         ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
     }
@@ -47,9 +56,24 @@ impl<T> Steal<T> {
 
     #[track_caller]
     pub fn steal(&self) -> T {
+        let caller = Location::caller();
+        tracing::debug!(
+            "starting steal of {T} *{ADDR:x} initiated by {caller}",
+            T = std::any::type_name::<T>(),
+            ADDR = (self as *const _ as u64),
+        );
         let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
         let value = value_ref.take();
-        value.expect("attempt to steal from stolen value")
+        let mut prev_stolen_by = self.prev_stolen_by.write();
+        let ret = value.unwrap_or_else(|| {
+            panic!(
+                "attempt to steal from stolen value, last stolen by: {}",
+                prev_stolen_by.expect("if its stolen then prev_stolen_by should be set")
+            );
+        });
+        assert_eq!(*prev_stolen_by, None);
+        *prev_stolen_by = Some(caller);
+        ret
     }
 
     /// Writers of rustc drivers often encounter stealing issues. This function makes it possible to
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 3276f516a52a1..aee88f9494249 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -109,6 +109,8 @@ pub enum DefKind {
     Use,
     /// An `extern` block.
     ForeignMod,
+    /// A contract associated with a function definition
+    Contract,
     /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`
     AnonConst,
     /// An inline constant, e.g. `const { 1 + 2 }`
@@ -173,6 +175,7 @@ impl DefKind {
             DefKind::LifetimeParam => "lifetime parameter",
             DefKind::Use => "import",
             DefKind::ForeignMod => "foreign module",
+            DefKind::Contract => "contract",
             DefKind::AnonConst => "constant expression",
             DefKind::InlineConst => "inline constant",
             DefKind::Field => "field",
@@ -230,7 +233,8 @@ impl DefKind {
             DefKind::Macro(..) => Some(Namespace::MacroNS),
 
             // Not namespaced.
-            DefKind::AnonConst
+            DefKind::Contract
+            | DefKind::AnonConst
             | DefKind::InlineConst
             | DefKind::Field
             | DefKind::LifetimeParam
@@ -282,6 +286,7 @@ impl DefKind {
             DefKind::Impl { .. } => DefPathData::Impl,
             DefKind::Closure => DefPathData::Closure,
             DefKind::SyntheticCoroutineBody => DefPathData::Closure,
+            DefKind::Contract => DefPathData::Contract,
         }
     }
 
@@ -323,6 +328,7 @@ impl DefKind {
             | DefKind::TyParam
             | DefKind::ConstParam
             | DefKind::LifetimeParam
+            | DefKind::Contract
             | DefKind::AnonConst
             | DefKind::InlineConst
             | DefKind::GlobalAsm
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 9873a58cfe99f..84d0323020fb1 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -291,6 +291,8 @@ pub enum DefPathData {
     OpaqueTy,
     /// An anonymous struct or union type i.e. `struct { foo: Type }` or `union { bar: Type }`
     AnonAdt,
+    /// A contract attached to a function definition
+    Contract,
 }
 
 impl Definitions {
@@ -415,7 +417,7 @@ impl DefPathData {
             TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
 
             Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
-            | OpaqueTy | AnonAdt => None,
+            | OpaqueTy | AnonAdt | Contract => None,
         }
     }
 
@@ -439,6 +441,7 @@ impl DefPathData {
             AnonConst => DefPathDataName::Anon { namespace: sym::constant },
             OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
             AnonAdt => DefPathDataName::Anon { namespace: sym::anon_adt },
+            Contract => DefPathDataName::Anon { namespace: sym::contract },
         }
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 2ef6fa53f4edd..2e02798cd40fd 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -17,18 +17,18 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{Ident, Symbol, kw, sym};
-use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Span};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{BytePos, ErrorGuaranteed, Span, DUMMY_SP};
 use rustc_target::asm::InlineAsmRegOrRegClass;
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 use tracing::debug;
 
-use crate::LangItem;
 use crate::def::{CtorKind, DefKind, Res};
 use crate::def_id::{DefId, LocalDefIdMap};
 pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
 use crate::intravisit::FnKind;
+use crate::LangItem;
 
 #[derive(Debug, Copy, Clone, HashStable_Generic)]
 pub struct Lifetime {
@@ -127,7 +127,11 @@ impl LifetimeName {
 
 impl fmt::Display for Lifetime {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) }
+        if self.ident.name != kw::Empty {
+            self.ident.name.fmt(f)
+        } else {
+            "'_".fmt(f)
+        }
     }
 }
 
@@ -1266,7 +1270,11 @@ impl DotDotPos {
     }
 
     pub fn as_opt_usize(&self) -> Option<usize> {
-        if self.0 == u32::MAX { None } else { Some(self.0 as usize) }
+        if self.0 == u32::MAX {
+            None
+        } else {
+            Some(self.0 as usize)
+        }
     }
 }
 
@@ -1441,6 +1449,18 @@ pub struct BodyId {
     pub hir_id: HirId,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+pub struct Contract {
+    pub def_id: LocalDefId,
+    pub body_id: BodyId,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+pub struct FnContractIds {
+    pub precond: Option<Contract>,
+    pub postcond: Option<Contract>,
+}
+
 /// The body of a function, closure, or constant value. In the case of
 /// a function, the body contains not only the function body itself
 /// (which is an expression), but also the argument patterns, since
@@ -1597,13 +1617,18 @@ pub enum BodyOwnerKind {
 
     /// Initializer of a `static` item.
     Static(Mutability),
+
+    /// Contract attached to a function
+    Contract,
 }
 
 impl BodyOwnerKind {
     pub fn is_fn_or_closure(self) -> bool {
         match self {
             BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
-            BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false,
+            BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) | BodyOwnerKind::Contract => {
+                false
+            }
         }
     }
 }
@@ -2596,10 +2621,10 @@ impl<'hir> Ty<'hir> {
             fn visit_ty(&mut self, t: &'v Ty<'v>) {
                 if matches!(
                     &t.kind,
-                    TyKind::Path(QPath::Resolved(_, Path {
-                        res: crate::def::Res::SelfTyAlias { .. },
-                        ..
-                    },))
+                    TyKind::Path(QPath::Resolved(
+                        _,
+                        Path { res: crate::def::Res::SelfTyAlias { .. }, .. },
+                    ))
                 ) {
                     self.0.push(t.span);
                     return;
@@ -2942,11 +2967,10 @@ impl<'hir> InlineAsmOperand<'hir> {
     }
 
     pub fn is_clobber(&self) -> bool {
-        matches!(self, InlineAsmOperand::Out {
-            reg: InlineAsmRegOrRegClass::Reg(_),
-            late: _,
-            expr: None
-        })
+        matches!(
+            self,
+            InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None }
+        )
     }
 }
 
@@ -3325,8 +3349,8 @@ impl<'hir> Item<'hir> {
         expect_const, (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
             ItemKind::Const(ty, generics, body), (ty, generics, *body);
 
-        expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId),
-            ItemKind::Fn(sig, generics, body), (sig, generics, *body);
+        expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, Option<&'hir FnContractIds>, BodyId),
+            ItemKind::Fn(sig, generics, contract_ids, body), (sig, generics, *contract_ids, *body);
 
         expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk);
 
@@ -3441,7 +3465,7 @@ pub enum ItemKind<'hir> {
     /// A `const` item.
     Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
     /// A function declaration.
-    Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId),
+    Fn(FnSig<'hir>, &'hir Generics<'hir>, Option<&'hir FnContractIds>, BodyId),
     /// A MBE macro definition (`macro_rules!` or `macro`).
     Macro(&'hir ast::MacroDef, MacroKind),
     /// A module.
@@ -3492,7 +3516,7 @@ pub struct Impl<'hir> {
 impl ItemKind<'_> {
     pub fn generics(&self) -> Option<&Generics<'_>> {
         Some(match *self {
-            ItemKind::Fn(_, ref generics, _)
+            ItemKind::Fn(_, ref generics, _, _)
             | ItemKind::TyAlias(_, ref generics)
             | ItemKind::Const(_, ref generics, _)
             | ItemKind::Enum(_, ref generics)
@@ -3677,7 +3701,7 @@ impl<'hir> OwnerNode<'hir> {
         match self {
             OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
             | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
-            | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
+            | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _, _), .. })
             | OwnerNode::ForeignItem(ForeignItem {
                 kind: ForeignItemKind::Fn(fn_sig, _, _), ..
             }) => Some(fn_sig),
@@ -3689,7 +3713,7 @@ impl<'hir> OwnerNode<'hir> {
         match self {
             OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
             | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
-            | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
+            | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _, _), .. })
             | OwnerNode::ForeignItem(ForeignItem {
                 kind: ForeignItemKind::Fn(fn_sig, _, _), ..
             }) => Some(fn_sig.decl),
@@ -3703,7 +3727,7 @@ impl<'hir> OwnerNode<'hir> {
                 kind:
                     ItemKind::Static(_, _, body)
                     | ItemKind::Const(_, _, body)
-                    | ItemKind::Fn(_, _, body),
+                    | ItemKind::Fn(_, _, _, body),
                 ..
             })
             | OwnerNode::TraitItem(TraitItem {
@@ -3882,7 +3906,7 @@ impl<'hir> Node<'hir> {
         match self {
             Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
             | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
-            | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
+            | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _, _), .. })
             | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
                 Some(fn_sig.decl)
             }
@@ -3912,7 +3936,7 @@ impl<'hir> Node<'hir> {
         match self {
             Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
             | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
-            | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. })
+            | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _, _), .. })
             | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_sig, _, _), .. }) => {
                 Some(fn_sig)
             }
@@ -4015,7 +4039,7 @@ impl<'hir> Node<'hir> {
     pub fn fn_kind(self) -> Option<FnKind<'hir>> {
         match self {
             Node::Item(i) => match i.kind {
-                ItemKind::Fn(ref sig, ref generics, _) => {
+                ItemKind::Fn(ref sig, ref generics, _, _) => {
                     Some(FnKind::ItemFn(i.ident, generics, sig.header))
                 }
                 _ => None,
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 58916d0586593..b6afcc06572f9 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -64,11 +64,11 @@
 //! This order consistency is required in a few places in rustc, for
 //! example coroutine inference, and possibly also HIR borrowck.
 
-use rustc_ast::visit::{VisitorResult, try_visit, visit_opt, walk_list};
+use rustc_ast::visit::{try_visit, visit_opt, walk_list, VisitorResult};
 use rustc_ast::{Attribute, Label};
-use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::Span;
 
 use crate::hir::*;
 
@@ -313,6 +313,12 @@ pub trait Visitor<'v>: Sized {
     fn visit_id(&mut self, _hir_id: HirId) -> Self::Result {
         Self::Result::output()
     }
+    fn visit_contract(&mut self, contract: &Contract) -> Self::Result {
+        self.visit_nested_body(contract.body_id)
+    }
+    fn visit_fn_contract_ids(&mut self, fn_contract_ids: &FnContractIds) -> Self::Result {
+        walk_fn_contract_ids(self, fn_contract_ids)
+    }
     fn visit_name(&mut self, _name: Symbol) -> Self::Result {
         Self::Result::output()
     }
@@ -487,6 +493,19 @@ pub trait Visitor<'v>: Sized {
     }
 }
 
+pub fn walk_fn_contract_ids<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    fn_contract_ids: &FnContractIds,
+) -> V::Result {
+    if let Some(precond) = &fn_contract_ids.precond {
+        try_visit!(visitor.visit_contract(precond));
+    }
+    if let Some(postcond) = &fn_contract_ids.postcond {
+        try_visit!(visitor.visit_contract(postcond));
+    }
+    V::Result::output()
+}
+
 pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result {
     try_visit!(visitor.visit_id(param.hir_id));
     visitor.visit_pat(param.pat)
@@ -513,8 +532,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
             try_visit!(visitor.visit_generics(generics));
             try_visit!(visitor.visit_nested_body(body));
         }
-        ItemKind::Fn(ref sig, ref generics, body_id) => {
+        ItemKind::Fn(ref sig, ref generics, fn_contract_ids, body_id) => {
             try_visit!(visitor.visit_id(item.hir_id()));
+            if let Some(fn_contract_ids) = fn_contract_ids {
+                try_visit!(visitor.visit_fn_contract_ids(fn_contract_ids));
+            }
             try_visit!(visitor.visit_fn(
                 FnKind::ItemFn(item.ident, generics, sig.header),
                 sig.decl,
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index 7da2cd93d4e01..f29c2ff15bf56 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -45,7 +45,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
             return None;
         }
         match tcx.hir_node_by_def_id(def_id.expect_local()) {
-            Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
+            Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _, _), .. }) => {
                 generics.params.is_empty().not().then_some(generics.span)
             }
             _ => {
@@ -59,7 +59,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
             return None;
         }
         match tcx.hir_node_by_def_id(def_id.expect_local()) {
-            Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => {
+            Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _, _), .. }) => {
                 Some(generics.where_clause_span)
             }
             _ => {
@@ -80,7 +80,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
             return None;
         }
         match tcx.hir_node_by_def_id(def_id.expect_local()) {
-            Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => {
+            Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _, _), .. }) => {
                 Some(fn_sig.decl.output.span())
             }
             _ => {
@@ -202,7 +202,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
     match start_t.kind() {
         ty::FnDef(..) => {
             if let Node::Item(it) = tcx.hir_node(start_id) {
-                if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
+                if let hir::ItemKind::Fn(sig, generics, _, _) = &it.kind {
                     let mut error = false;
                     if !generics.params.is_empty() {
                         tcx.dcx().emit_err(errors::StartFunctionParameters { span: generics.span });
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 06317a3b3049c..70f6da6a30956 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -28,7 +28,7 @@ fn equate_intrinsic_type<'tcx>(
     sig: ty::PolyFnSig<'tcx>,
 ) {
     let (generics, span) = match tcx.hir_node_by_def_id(def_id) {
-        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
+        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _, _), .. })
         | hir::Node::ForeignItem(hir::ForeignItem {
             kind: hir::ForeignItemKind::Fn(_, _, generics),
             ..
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 3a9d2640eee93..f53b90527aac0 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -2234,7 +2234,8 @@ fn lint_redundant_lifetimes<'tcx>(
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Closure
-        | DefKind::SyntheticCoroutineBody => return,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => return,
     }
 
     // The ordering of this lifetime map is a bit subtle.
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index f63e2d40e3906..93bad3f5b76c2 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1315,7 +1315,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
             generics,
             ..
         })
-        | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
+        | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _, _), .. }) => {
             infer_return_ty_for_fn_sig(sig, generics, def_id, &icx)
         }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 14b6b17ed18a7..634081c287e72 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -8,8 +8,8 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
+use rustc_span::symbol::{kw, Symbol};
 use rustc_span::Span;
-use rustc_span::symbol::{Symbol, kw};
 use tracing::{debug, instrument};
 
 use crate::delegation::inherit_generics_for_delegation_item;
@@ -326,7 +326,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
         prev + type_start
     };
 
-    const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
+    const TYPE_DEFAULT_NOT_ALLOWED: &'static str =
+        "defaults for type parameters are only allowed in \
     `struct`, `enum`, `type`, or `trait` definitions";
 
     own_params.extend(hir_generics.params.iter().filter_map(|param| match param.kind {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 6d30f7c7b9d07..1b0a28764981b 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -9,7 +9,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::{Span, DUMMY_SP};
 use tracing::{debug, instrument, trace};
 
 use crate::bounds::Bounds;
@@ -379,10 +379,10 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
     for param in opaque_own_params {
         let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
         if let ty::ReEarlyParam(..) = *orig_lifetime {
-            let dup_lifetime = ty::Region::new_early_param(tcx, ty::EarlyParamRegion {
-                index: param.index,
-                name: param.name,
-            });
+            let dup_lifetime = ty::Region::new_early_param(
+                tcx,
+                ty::EarlyParamRegion { index: param.index, name: param.name },
+            );
             let span = tcx.def_span(param.def_id);
             predicates.push((
                 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index c8852a3a3695a..ca0ef9664f923 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -521,7 +521,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
             _ => {}
         }
         match item.kind {
-            hir::ItemKind::Fn(_, generics, _) => {
+            hir::ItemKind::Fn(_, generics, _, _) => {
                 self.visit_early_late(item.hir_id(), generics, |this| {
                     intravisit::walk_item(this, item);
                 });
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 11c0450bfe211..b673a223e745b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -3,8 +3,8 @@ use rustc_errors::codes::*;
 use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_lint_defs::Applicability;
 use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS;
+use rustc_lint_defs::Applicability;
 use rustc_span::Span;
 use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
 
@@ -189,7 +189,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // 2. Functions inside trait blocks
         // 3. Functions inside impl blocks
         let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _, _), .. }) => {
                 (sig, generics)
             }
             hir::Node::TraitItem(hir::TraitItem {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 9fe6a8ee3425a..d103cee946c18 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -363,6 +363,7 @@ impl<'a> State<'a> {
                     generics,
                     arg_names,
                     None,
+                    None,
                 );
                 self.end(); // end head-ibox
                 self.word(";");
@@ -522,7 +523,7 @@ impl<'a> State<'a> {
                 self.word(";");
                 self.end(); // end the outer cbox
             }
-            hir::ItemKind::Fn(ref sig, generics, body) => {
+            hir::ItemKind::Fn(ref sig, generics, fn_contract_ids, body) => {
                 self.head("");
                 self.print_fn(
                     sig.decl,
@@ -530,6 +531,7 @@ impl<'a> State<'a> {
                     Some(item.ident.name),
                     generics,
                     &[],
+                    fn_contract_ids,
                     Some(body),
                 );
                 self.word(" ");
@@ -792,7 +794,7 @@ impl<'a> State<'a> {
         arg_names: &[Ident],
         body_id: Option<hir::BodyId>,
     ) {
-        self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id);
+        self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, None, body_id);
     }
 
     fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
@@ -1942,6 +1944,7 @@ impl<'a> State<'a> {
         name: Option<Symbol>,
         generics: &hir::Generics<'_>,
         arg_names: &[Ident],
+        fn_contract_ids: Option<&hir::FnContractIds>,
         body_id: Option<hir::BodyId>,
     ) {
         self.print_fn_header_info(header);
@@ -1982,6 +1985,9 @@ impl<'a> State<'a> {
         self.pclose();
 
         self.print_fn_output(decl);
+        if let Some(contract_ids) = fn_contract_ids {
+            self.print_contracts(contract_ids);
+        }
         self.print_where_clause(generics)
     }
 
@@ -2146,6 +2152,23 @@ impl<'a> State<'a> {
         self.print_ident(lifetime.ident)
     }
 
+    fn print_contracts(&mut self, fn_contract_ids: &hir::FnContractIds) {
+        if let Some(precond) = fn_contract_ids.precond {
+            self.space();
+            self.word("rustc_contract_requires");
+            self.popen();
+            self.ann.nested(self, Nested::Body(precond.body_id));
+            self.pclose();
+        }
+        if let Some(postcond) = fn_contract_ids.postcond {
+            self.space();
+            self.word("rustc_contract_ensures");
+            self.popen();
+            self.ann.nested(self, Nested::Body(postcond.body_id));
+            self.pclose();
+        }
+    }
+
     fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {
         if generics.predicates.is_empty() {
             return;
@@ -2260,6 +2283,7 @@ impl<'a> State<'a> {
             generics,
             arg_names,
             None,
+            None,
         );
         self.end();
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index fa471647d02d0..44df9647ccf24 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1988,7 +1988,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn parent_item_span(&self, id: HirId) -> Option<Span> {
         let node = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
         match node {
-            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
+            Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, _, body_id), .. })
             | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
                 let body = self.tcx.hir().body(body_id);
                 if let ExprKind::Block(block, _) = &body.value.kind {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 1df4d32f3cbac..9f74c016597b3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -989,6 +989,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ..
                     },
                     hir::Generics { params, predicates, .. },
+                    _,
                     _body_id,
                 ),
             ..
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 63cf483aa2274..885b97cda2fab 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1924,7 +1924,7 @@ fn drop_location_span(tcx: TyCtxt<'_>, hir_id: HirId) -> Span {
     let owner_node = tcx.hir_node(owner_id);
     let owner_span = match owner_node {
         hir::Node::Item(item) => match item.kind {
-            hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id),
+            hir::ItemKind::Fn(_, _, _, owner_id) => tcx.hir().span(owner_id.hir_id),
             _ => {
                 bug!("Drop location span error: need to handle more ItemKind '{:?}'", item.kind);
             }
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index b193b81f6de48..a3241feba37d8 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -7,16 +7,16 @@ use std::mem;
 use rustc_data_structures::unord::ExtendUnord;
 use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
-use rustc_hir::HirId;
 use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::HirId;
 use rustc_middle::span_bug;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable};
-use rustc_span::Span;
 use rustc_span::symbol::sym;
+use rustc_span::Span;
 use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
 use rustc_trait_selection::solve;
 use tracing::{debug, instrument};
@@ -56,7 +56,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id);
                 wbcx.visit_node_id(body.value.span, item_hir_id);
             }
-            hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
+            hir::BodyOwnerKind::Contract | hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => {
+                ()
+            }
         }
         wbcx.visit_body(body);
         wbcx.visit_min_capture_map();
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 8bd9c899a6286..f38e60aa4ee48 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -349,6 +349,7 @@ impl EarlyLintPass for UnsafeCode {
             ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. },
             _,
             _,
+            _,
             body,
         ) = fk
         {
@@ -1036,7 +1037,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
             }
         };
         match it.kind {
-            hir::ItemKind::Fn(.., generics, _) => {
+            hir::ItemKind::Fn(.., generics, _, _) => {
                 if let Some(no_mangle_attr) = attr::find_by_name(attrs, sym::no_mangle) {
                     check_no_mangle_on_generic_fn(no_mangle_attr, None, generics, it.span);
                 }
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 2285877c9ef26..3f8f5e7ef8bde 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -157,7 +157,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
 
         // Explicitly check for lints associated with 'closure_id', since
         // it does not have a corresponding AST node
-        if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk {
+        if let ast_visit::FnKind::Fn(_, _, sig, _, _, _, _) = fk {
             if let Some(coroutine_kind) = sig.header.coroutine_kind {
                 self.check_id(coroutine_kind.closure_id());
             }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index afe03531861c9..8f426ad26f4bb 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -878,7 +878,8 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::Field
         | DefKind::Impl { .. }
         | DefKind::Closure
-        | DefKind::SyntheticCoroutineBody => true,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => true,
         DefKind::ForeignMod | DefKind::GlobalAsm => false,
     }
 }
@@ -902,7 +903,8 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
         | DefKind::AssocConst
         | DefKind::Macro(_)
         | DefKind::Field
-        | DefKind::Impl { .. } => true,
+        | DefKind::Impl { .. } 
+        | DefKind::Contract => true,
         // Tools may want to be able to detect their tool lints on
         // closures from upstream crates, too. This is used by
         // https://github.com/model-checking/kani and is not a performance
@@ -956,7 +958,8 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Closure
-        | DefKind::SyntheticCoroutineBody => false,
+        | DefKind::SyntheticCoroutineBody
+        | DefKind::Contract => false,
     }
 }
 
@@ -993,7 +996,8 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::Impl { .. }
         | DefKind::Closure
         | DefKind::ExternCrate
-        | DefKind::SyntheticCoroutineBody => false,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => false,
     }
 }
 
@@ -1029,7 +1033,8 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::ExternCrate
-        | DefKind::SyntheticCoroutineBody => false,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => false,
     }
 }
 
@@ -1124,7 +1129,8 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
         | DefKind::GlobalAsm
         | DefKind::Closure
         | DefKind::ExternCrate
-        | DefKind::SyntheticCoroutineBody => false,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => false,
         DefKind::TyAlias => tcx.type_alias_is_lazy(def_id),
     }
 }
@@ -1161,7 +1167,8 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::Use
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
-        | DefKind::ExternCrate => false,
+        | DefKind::ExternCrate 
+        | DefKind::Contract => false,
     }
 }
 
@@ -1185,7 +1192,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::ConstParam
         | DefKind::AnonConst
         | DefKind::InlineConst
-        | DefKind::SyntheticCoroutineBody => true,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => true,
 
         DefKind::OpaqueTy => {
             let origin = tcx.opaque_type_origin(def_id);
@@ -1258,7 +1266,8 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::ExternCrate
-        | DefKind::SyntheticCoroutineBody => false,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => false,
     }
 }
 
@@ -1296,7 +1305,8 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::ExternCrate
-        | DefKind::SyntheticCoroutineBody => false,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => false,
     }
 }
 
@@ -1330,7 +1340,8 @@ fn should_encode_const(def_kind: DefKind) -> bool {
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::ExternCrate
-        | DefKind::SyntheticCoroutineBody => false,
+        | DefKind::SyntheticCoroutineBody 
+        | DefKind::Contract => false,
     }
 }
 
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 3a6f3543317f6..4cd49d8a3aa0e 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -156,6 +156,7 @@ fixed_size_enum! {
         ( Impl { of_trait: false }                 )
         ( Impl { of_trait: true }                  )
         ( Closure                                  )
+        ( Contract                                 )
         ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: false } )
         ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: false } )
         ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: false } )
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 8fd5ff1f369d4..21225a31bc081 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,16 +1,16 @@
-use rustc_ast::visit::{VisitorResult, walk_list};
+use rustc_ast::visit::{walk_list, VisitorResult};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in};
+use rustc_data_structures::sync::{par_for_each_in, try_par_for_each_in, DynSend, DynSync};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::*;
 use rustc_middle::hir::nested_filter;
 use rustc_span::def_id::StableCrateId;
-use rustc_span::symbol::{Ident, Symbol, kw, sym};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_target::spec::abi::Abi;
 use {rustc_ast as ast, rustc_hir_pretty as pprust_hir};
@@ -311,6 +311,7 @@ impl<'hir> Map<'hir> {
             DefKind::Static { safety: _, mutability, nested: false } => {
                 BodyOwnerKind::Static(mutability)
             }
+            DefKind::Contract => BodyOwnerKind::Contract,
             dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
         }
     }
@@ -334,6 +335,7 @@ impl<'hir> Map<'hir> {
             }
             BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
             BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
+            BodyOwnerKind::Contract => return None,
         };
 
         Some(ccx)
@@ -1352,6 +1354,17 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
         intravisit::walk_foreign_item(self, item)
     }
 
+    fn visit_fn_contract_ids(&mut self, c: &FnContractIds) {
+        if let Some(precond) = c.precond {
+            self.body_owners.push(precond.def_id);
+        }
+        if let Some(postcond) = c.postcond {
+            self.body_owners.push(postcond.def_id);
+        }
+        // TODO: add contract ids to self.body_owners, analogous to items and consts.
+        intravisit::walk_fn_contract_ids(self, c)
+    }
+
     fn visit_anon_const(&mut self, c: &'hir AnonConst) {
         self.body_owners.push(c.def_id);
         intravisit::walk_anon_const(self, c)
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index fe865b8a51508..4b6a7f33851fc 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -16,7 +16,7 @@ use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
-use rustc_index::{IndexVec, newtype_index};
+use rustc_index::{newtype_index, IndexVec};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
 use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::AllocId;
@@ -102,6 +102,7 @@ thir_with_elements! {
 pub enum BodyTy<'tcx> {
     Const(Ty<'tcx>),
     Fn(FnSig<'tcx>),
+    Contract,
 }
 
 /// Description of a type-checked function parameter.
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 1bdcae4dfb479..893d9d2993074 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -31,7 +31,7 @@ use rustc_errors::{
 };
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
@@ -46,16 +46,16 @@ use rustc_session::config::CrateType;
 use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
 use rustc_session::{Limit, MetadataKind, Session};
-use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
-use rustc_span::symbol::{Ident, Symbol, kw, sym};
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::def_id::{DefPathHash, StableCrateId, CRATE_DEF_ID};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use rustc_type_ir::TyKind::*;
 use rustc_type_ir::fold::TypeFoldable;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 pub use rustc_type_ir::lift::Lift;
 use rustc_type_ir::solve::SolverMode;
-use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph};
+use rustc_type_ir::TyKind::*;
+use rustc_type_ir::{search_graph, CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
 use tracing::{debug, trace};
 
 use crate::arena::Arena;
@@ -1027,10 +1027,10 @@ impl<'tcx> CommonLifetimes<'tcx> {
             .map(|i| {
                 (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
                     .map(|v| {
-                        mk(ty::ReBound(ty::DebruijnIndex::from(i), ty::BoundRegion {
-                            var: ty::BoundVar::from(v),
-                            kind: ty::BrAnon,
-                        }))
+                        mk(ty::ReBound(
+                            ty::DebruijnIndex::from(i),
+                            ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon },
+                        ))
                     })
                     .collect()
             })
@@ -1396,7 +1396,11 @@ impl<'tcx> TyCtxt<'tcx> {
             self.codegen_fn_attrs(def_id)
         } else if matches!(
             def_kind,
-            DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst
+            DefKind::AnonConst
+                | DefKind::AssocConst
+                | DefKind::Const
+                | DefKind::InlineConst
+                | DefKind::Contract
         ) {
             CodegenFnAttrs::EMPTY
         } else {
@@ -1452,11 +1456,9 @@ impl<'tcx> TyCtxt<'tcx> {
             };
             debug!("layout_scalar_valid_range: attr={:?}", attr);
             if let Some(
-                &[
-                    ast::MetaItemInner::Lit(ast::MetaItemLit {
-                        kind: ast::LitKind::Int(a, _), ..
-                    }),
-                ],
+                &[ast::MetaItemInner::Lit(ast::MetaItemLit {
+                    kind: ast::LitKind::Int(a, _), ..
+                })],
             ) = attr.meta_item_list().as_deref()
             {
                 Bound::Included(a.get())
@@ -2108,7 +2110,7 @@ macro_rules! nop_lift {
 
                 tcx.interners
                     .$set
-                    .contains_pointer_to(&InternedInSet(&*self.0.0))
+                    .contains_pointer_to(&InternedInSet(&*self.0 .0))
                     // SAFETY: `self` is interned and therefore valid
                     // for the entire lifetime of the `TyCtxt`.
                     .then(|| unsafe { mem::transmute(self) })
@@ -2550,7 +2552,11 @@ impl<'tcx> TyCtxt<'tcx> {
         pred: Predicate<'tcx>,
         binder: Binder<'tcx, PredicateKind<'tcx>>,
     ) -> Predicate<'tcx> {
-        if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
+        if pred.kind() != binder {
+            self.mk_predicate(binder)
+        } else {
+            pred
+        }
     }
 
     pub fn check_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) -> bool {
@@ -2733,11 +2739,9 @@ impl<'tcx> TyCtxt<'tcx> {
         eps: &[PolyExistentialPredicate<'tcx>],
     ) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
         assert!(!eps.is_empty());
-        assert!(
-            eps.array_windows()
-                .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
-                    != Ordering::Greater)
-        );
+        assert!(eps
+            .array_windows()
+            .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder()) != Ordering::Greater));
         self.intern_poly_existential_predicates(eps)
     }
 
@@ -2767,9 +2771,9 @@ impl<'tcx> TyCtxt<'tcx> {
     where
         I: Iterator<Item = T>,
         T: CollectAndApply<
-                &'tcx ty::CapturedPlace<'tcx>,
-                &'tcx List<&'tcx ty::CapturedPlace<'tcx>>,
-            >,
+            &'tcx ty::CapturedPlace<'tcx>,
+            &'tcx List<&'tcx ty::CapturedPlace<'tcx>>,
+        >,
     {
         T::collect_and_apply(iter, |xs| self.intern_captures(xs))
     }
@@ -2810,9 +2814,9 @@ impl<'tcx> TyCtxt<'tcx> {
     where
         I: Iterator<Item = T>,
         T: CollectAndApply<
-                PolyExistentialPredicate<'tcx>,
-                &'tcx List<PolyExistentialPredicate<'tcx>>,
-            >,
+            PolyExistentialPredicate<'tcx>,
+            &'tcx List<PolyExistentialPredicate<'tcx>>,
+        >,
     {
         T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
     }
@@ -3053,12 +3057,15 @@ impl<'tcx> TyCtxt<'tcx> {
                     }
 
                     let generics = self.generics_of(new_parent);
-                    return ty::Region::new_early_param(self, ty::EarlyParamRegion {
-                        index: generics
-                            .param_def_id_to_index(self, ebv.to_def_id())
-                            .expect("early-bound var should be present in fn generics"),
-                        name: self.item_name(ebv.to_def_id()),
-                    });
+                    return ty::Region::new_early_param(
+                        self,
+                        ty::EarlyParamRegion {
+                            index: generics
+                                .param_def_id_to_index(self, ebv.to_def_id())
+                                .expect("early-bound var should be present in fn generics"),
+                            name: self.item_name(ebv.to_def_id()),
+                        },
+                    );
                 }
                 Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => {
                     let new_parent = self.local_parent(lbv);
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 8c20d2e0d3a62..4f8175a99408e 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,6 +1,6 @@
 use itertools::Itertools;
-use rustc_apfloat::Float;
 use rustc_apfloat::ieee::{Double, Half, Quad, Single};
+use rustc_apfloat::Float;
 use rustc_ast::attr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sorted_map::SortedIndexMultiMap;
@@ -57,6 +57,7 @@ pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx
             let build_mir = |thir: &Thir<'tcx>| match thir.body_type {
                 thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig),
                 thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty),
+                thir::BodyTy::Contract => construct_contract(tcx, def, thir, expr),
             };
 
             // this must run before MIR dump, because
@@ -593,6 +594,35 @@ fn construct_const<'a, 'tcx>(
     builder.finish()
 }
 
+fn construct_contract<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def: LocalDefId,
+    thir: &Thir<'tcx>,
+    expr: ExprId,
+) -> Body<'tcx> {
+    let span = tcx.def_span(def);
+    let hir_id = tcx.local_def_id_to_hir_id(def);
+    let infcx = tcx.infer_ctxt().build();
+    let fn_decl = tcx
+        .hir()
+        .fn_decl_by_hir_id(hir_id)
+        .unwrap_or_else(|| span_bug!(span, "can't build MIR for {:?}", def));
+    let span_with_body = tcx.hir().span_with_body(hir_id);
+    let return_ty_span = fn_decl.output.span();
+    let return_ty = tcx.types.bool;
+    let mut builder =
+        Builder::new(thir, infcx, def, hir_id, span_with_body, 0, return_ty, return_ty_span, None);
+    let arguments = &thir.params;
+    let body = tcx.hir().body_owned_by(def);
+    let arg_scope =
+        region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::Arguments };
+    let block = builder.args_and_body(START_BLOCK, arguments, arg_scope, expr).into_block();
+    let source_info = builder.source_info(span_with_body);
+    builder.cfg.terminate(block, source_info, TerminatorKind::Return);
+    builder.build_drop_trees();
+    builder.finish()
+}
+
 /// Construct MIR for an item that has had errors in type checking.
 ///
 /// This is required because we may still want to run MIR passes on an item
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 377931e3be730..a8624fb8c8d11 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -5,10 +5,10 @@
 use rustc_data_structures::steal::Steal;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
-use rustc_hir::HirId;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
+use rustc_hir::HirId;
 use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
@@ -79,6 +79,8 @@ impl<'tcx> Cx<'tcx> {
             // fetch the fully liberated fn signature (that is, all bound
             // types/lifetimes replaced)
             BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
+        } else if let hir::BodyOwnerKind::Contract = hir.body_owner_kind(def) {
+            BodyTy::Contract
         } else {
             // Get the revealed type of this const. This is *not* the adjusted
             // type of its body, which may be a subtype of this type. For
@@ -182,11 +184,9 @@ impl<'tcx> Cx<'tcx> {
             let ty = if fn_decl.c_variadic && index == fn_decl.inputs.len() {
                 let va_list_did = self.tcx.require_lang_item(LangItem::VaList, Some(param.span));
 
-                self.tcx.type_of(va_list_did).instantiate(self.tcx, &[self
-                    .tcx
-                    .lifetimes
-                    .re_erased
-                    .into()])
+                self.tcx
+                    .type_of(va_list_did)
+                    .instantiate(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
             } else {
                 fn_sig.inputs()[index]
             };
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index ae77bce6bb199..f7c1430b6b23c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -3,7 +3,7 @@ use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::codes::*;
-use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_err};
+use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed, MultiSpan};
 use rustc_hir::def::*;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
@@ -22,7 +22,7 @@ use rustc_session::lint::builtin::{
     BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
 };
 use rustc_span::hygiene::DesugaringKind;
-use rustc_span::{Span, sym};
+use rustc_span::{sym, Span};
 use tracing::instrument;
 
 use crate::errors::*;
@@ -49,11 +49,15 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err
 
     let origin = match tcx.def_kind(def_id) {
         DefKind::AssocFn | DefKind::Fn => "function argument",
+        DefKind::Contract => "contract-inherited function argument",
         DefKind::Closure => "closure argument",
         // other types of MIR don't have function parameters, and we don't need to
         // categorize those for the irrefutable check.
         _ if thir.params.is_empty() => "",
-        kind => bug!("unexpected function parameters in THIR: {kind:?} {def_id:?}"),
+        kind => bug!(
+            "unexpected function parameters in THIR: {kind:?} {def_id:?}, params: {:?}",
+            thir.params
+        ),
     };
 
     for param in thir.params.iter() {
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index e049fe996645a..76077485ec780 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -5,9 +5,9 @@
 //! generic parameters are unused (and eventually, in what ways generic parameters are used - only
 //! for their size, offset of a field, etc.).
 
-use rustc_hir::ConstContext;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
+use rustc_hir::ConstContext;
 use rustc_middle::mir::visit::{TyContext, Visitor};
 use rustc_middle::mir::{self, Local, LocalDecl, Location};
 use rustc_middle::query::Providers;
@@ -161,6 +161,7 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
+        | DefKind::Contract
         | DefKind::Impl { .. } => {
             for param in &generics.own_params {
                 debug!(?param, "(other)");
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 5aebe716b0a10..e06f51479416c 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -295,6 +295,21 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Parses an optional fn contract (`requires XXX ensures YYY``)
+    pub(super) fn parse_contract(&mut self) -> PResult<'a, ast::FnContract> {
+        let pre_cond = if self.eat_keyword(kw::RustcContractRequires) {
+            Some(self.parse_expr()?)
+        } else {
+            None
+        };
+        let post_cond = if self.eat_keyword(kw::RustcContractEnsures) {
+            Some(self.parse_expr()?)
+        } else {
+            None
+        };
+        Ok(ast::FnContract { requires: pre_cond, ensures: post_cond })
+    }
+
     /// 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 36733726564fb..0d72ae712f7c3 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -197,9 +197,9 @@ 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(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
                 // EXTERN CRATE
@@ -2312,7 +2312,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, 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`
@@ -2338,18 +2338,20 @@ 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.
         let fn_params_end =
             if generics.where_clause.has_where_token { Some(fn_params_end) } else { None };
-
+        
         let mut sig_hi = self.prev_token.span;
         // Either `;` or `{ ... }`.
         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_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 44a62383e6eed..667c70c73f0bf 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1531,7 +1531,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         };
 
         let Some(ItemLike::Item(Item {
-            kind: ItemKind::Fn(FnSig { decl, .. }, generics, _), ..
+            kind: ItemKind::Fn(FnSig { decl, .. }, generics, _, _), ..
         })) = item
         else {
             bug!("should be a function item");
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index b2f8d7dadff37..b2b6f1407f7cc 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -31,7 +31,7 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
         }
 
         let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, _, body_id), .. })
             | hir::Node::TraitItem(hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
                 ..
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 751c87a9fe519..f135f9f25b847 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -380,7 +380,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
                     )
                 }
             }
-            hir::ItemKind::Fn(ref item_fn_sig, _, _) => {
+            hir::ItemKind::Fn(ref item_fn_sig, _, _, _) => {
                 fn_sig = Some(item_fn_sig);
             }
             _ => {}
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index f67c4cb922cee..e40cd02cd952a 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -20,12 +20,12 @@ use errors::{
     ItemIsPrivate, PrivateInterfacesOrBoundsLint, ReportEffectiveVisibility, UnnameableTypesLint,
     UnnamedItemIsPrivate,
 };
+use rustc_ast::visit::{try_visit, VisitorResult};
 use rustc_ast::MacroDef;
-use rustc_ast::visit::{VisitorResult, try_visit};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
 use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
@@ -37,9 +37,9 @@ use rustc_middle::ty::{
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
-use rustc_span::Span;
 use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{Ident, kw, sym};
+use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::Span;
 use tracing::debug;
 use {rustc_attr as attr, rustc_hir as hir};
 
@@ -75,7 +75,7 @@ pub trait DefIdVisitor<'tcx> {
 
     fn tcx(&self) -> TyCtxt<'tcx>;
     fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
-    -> Self::Result;
+        -> Self::Result;
 
     /// Not overridden, but used to actually visit types and traits.
     fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
@@ -116,7 +116,11 @@ where
             "trait",
             &trait_ref.print_only_trait_path()
         ));
-        if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
+        if V::SHALLOW {
+            V::Result::output()
+        } else {
+            args.visit_with(self)
+        }
     }
 
     fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result {
@@ -201,9 +205,10 @@ where
                 // so we need to visit the self type additionally.
                 if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
                     if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
-                        try_visit!(
-                            tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)
-                        );
+                        try_visit!(tcx
+                            .type_of(impl_def_id)
+                            .instantiate_identity()
+                            .visit_with(self));
                     }
                 }
             }
@@ -291,7 +296,11 @@ where
             }
         }
 
-        if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) }
+        if V::SHALLOW {
+            V::Result::output()
+        } else {
+            ty.super_visit_with(self)
+        }
     }
 
     fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
@@ -301,7 +310,11 @@ where
 }
 
 fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
-    if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
+    if vis1.is_at_least(vis2, tcx) {
+        vis2
+    } else {
+        vis1
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -607,6 +620,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             DefKind::AssocConst
             | DefKind::AssocTy
             | DefKind::ConstParam
+            | DefKind::Contract
             | DefKind::Ctor(_, _)
             | DefKind::Enum
             | DefKind::ForeignTy
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 0145ffd3a4b7c..c41cdd003eccf 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -262,8 +262,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 | DefKind::GlobalAsm
                 | DefKind::Closure
                 | DefKind::SyntheticCoroutineBody
-                | DefKind::Impl { .. },
-                _,
+                | DefKind::Impl { .. }
+                | DefKind::Contract,
+                _
             )
             | Res::Local(..)
             | Res::SelfTyParam { .. }
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 0047f2c4b51e9..e8b939ede9aed 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -240,11 +240,14 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
 
     fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
         match fn_kind {
-            FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body)
+            FnKind::Fn(_ctxt, _ident,
+                FnSig { header, decl, span: _ }, 
+                _vis, generics, contract, body)
                 if let Some(coroutine_kind) = header.coroutine_kind =>
             {
                 self.visit_fn_header(header);
                 self.visit_generics(generics);
+                self.visit_contract(contract); // XXX
 
                 // 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 66c1ff93ce1ce..106c1261d33d3 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -961,8 +961,8 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
         match fn_kind {
             // Bail if the function is foreign, and thus cannot validly have
             // a body, or if there's no body for some other reason.
-            FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
-            | FnKind::Fn(_, _, sig, _, generics, None) => {
+            FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _, _)
+            | FnKind::Fn(_, _, sig, _, generics, _, None) => {
                 self.visit_fn_header(&sig.header);
                 self.visit_generics(generics);
                 self.with_lifetime_rib(
@@ -1002,7 +1002,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(_, _, sig, _, generics, body) => {
+                    FnKind::Fn(_, _, sig, _, generics, contract, body) => {
                         this.visit_generics(generics);
 
                         let declaration = &sig.decl;
@@ -1033,6 +1033,8 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
                             },
                         );
 
+                        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_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index fce5ec36c661b..c6ffdd3b94fa8 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -3169,7 +3169,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     {
                         let pre = if lt.kind == MissingLifetimeKind::Ampersand
                             && let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, sig, _, _, _) = kind
+                            && let FnKind::Fn(_, _, sig, _, _, _, _) = kind
                             && !sig.decl.inputs.is_empty()
                             && let sugg = sig
                                 .decl
@@ -3210,7 +3210,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         } else if (lt.kind == MissingLifetimeKind::Ampersand
                             || lt.kind == MissingLifetimeKind::Underscore)
                             && let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, sig, _, _, _) = kind
+                            && let FnKind::Fn(_, _, sig, _, _, _, _) = kind
                             && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output
                             && !sig.decl.inputs.is_empty()
                             && let arg_refs = sig
@@ -3270,7 +3270,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
                         let mut sugg = vec![(lt.span, String::new())];
                         if let Some((kind, _span)) = self.diag_metadata.current_function
-                            && let FnKind::Fn(_, _, sig, _, _, _) = kind
+                            && let FnKind::Fn(_, _, sig, _, _, _, _) = kind
                             && let ast::FnRetTy::Ty(ty) = &sig.decl.output
                         {
                             let mut lt_finder =
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 53834198f6328..8a161ba310951 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -7,7 +7,7 @@
 
 use std::fmt::Write as _;
 
-use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, CASE_INSENSITIVE, ToBaseN};
+use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY, CASE_INSENSITIVE};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_middle::bug;
@@ -22,8 +22,8 @@ use rustc_target::abi::Integer;
 use rustc_target::spec::abi::Abi;
 use tracing::instrument;
 
-use crate::cfi::typeid::TypeIdOptions;
 use crate::cfi::typeid::itanium_cxx_abi::transform::{TransformTy, TransformTyOptions};
+use crate::cfi::typeid::TypeIdOptions;
 
 /// Options for encode_ty.
 pub(crate) type EncodeTyOptions = TypeIdOptions;
@@ -714,7 +714,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
             | hir::definitions::DefPathData::GlobalAsm
             | hir::definitions::DefPathData::MacroNs(..)
             | hir::definitions::DefPathData::LifetimeNs(..)
-            | hir::definitions::DefPathData::AnonAdt => {
+            | hir::definitions::DefPathData::AnonAdt
+            | hir::definitions::DefPathData::Contract => {
                 bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
             }
         });
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 9b27b94fb5a56..1039aa8c3391d 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -111,7 +111,8 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::Impl { .. }
-        | DefKind::GlobalAsm => {
+        | DefKind::GlobalAsm 
+        | DefKind::Contract => {
             unreachable!("Not a valid item kind: {kind:?}");
         }
         DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index cc3bda99a117b..9e8792346a0d0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -103,6 +103,8 @@ symbols! {
         MacroRules:         "macro_rules",
         Raw:                "raw",
         Reuse:              "reuse",
+        RustcContractEnsures:  "rustc_contract_ensures",
+        RustcContractRequires: "rustc_contract_requires",
         Safe:               "safe",
         Union:              "union",
         Yeet:               "yeet",
@@ -650,6 +652,7 @@ symbols! {
         const_try,
         constant,
         constructor,
+        contract,
         convert_identity,
         copy,
         copy_closures,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index f3da7ff1ca7b0..099053435089b 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -774,7 +774,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             | DefPathData::Impl
             | DefPathData::MacroNs(_)
             | DefPathData::LifetimeNs(_)
-            | DefPathData::AnonAdt => {
+            | DefPathData::AnonAdt
+            | DefPathData::Contract => {
                 bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
             }
         };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index bd78a6ee3aff7..07ceba89123fc 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1729,7 +1729,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             return None;
         };
         let tykind = match self.tcx.hir_node_by_def_id(trace.cause.body_id) {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => {
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, _, body_id), .. }) => {
                 let body = hir.body(*body_id);
                 struct LetVisitor {
                     span: Span,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index 709b6eb18e35f..217f42f519ff8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -816,7 +816,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     pat.walk(&mut find_compatible_candidates);
                 }
 
-                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
+                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, _, body), .. })
                 | hir::Node::ImplItem(hir::ImplItem {
                     kind: hir::ImplItemKind::Fn(_, body), ..
                 })
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 824c25db07d2e..a39ec249722aa 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -898,7 +898,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
         let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);
         let body_id = match self.tcx.hir_node(hir_id) {
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id,
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, _, body_id), .. }) => body_id,
             _ => return false,
         };
         let ControlFlow::Break(expr) = (FindMethodSubexprOfTry { search_span: span })
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 87834c329e19f..ffecaea64ff04 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -308,7 +308,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     ..
                 })
                 | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(fn_sig, generics, _), ..
+                    kind: hir::ItemKind::Fn(fn_sig, generics, _, _), ..
                 }) if projection.is_some() => {
                     // Missing restriction on associated type of type parameter (unmet projection).
                     suggest_restriction(
@@ -352,7 +352,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         | hir::ItemKind::Union(_, generics)
                         | hir::ItemKind::Trait(_, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
-                        | hir::ItemKind::Fn(_, generics, _)
+                        | hir::ItemKind::Fn(_, generics, _, _)
                         | hir::ItemKind::TyAlias(_, generics)
                         | hir::ItemKind::Const(_, generics, _)
                         | hir::ItemKind::TraitAlias(generics, _),
@@ -418,7 +418,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         | hir::ItemKind::Union(_, generics)
                         | hir::ItemKind::Trait(_, _, generics, ..)
                         | hir::ItemKind::Impl(hir::Impl { generics, .. })
-                        | hir::ItemKind::Fn(_, generics, _)
+                        | hir::ItemKind::Fn(_, generics, _, _)
                         | hir::ItemKind::TyAlias(_, generics)
                         | hir::ItemKind::Const(_, generics, _)
                         | hir::ItemKind::TraitAlias(generics, _),
@@ -1729,7 +1729,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     ) -> bool {
         let hir = self.tcx.hir();
         let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
-        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = node
+        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, _, body_id), .. }) = node
             && let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
             && sig.decl.output.span().overlaps(span)
             && blk.expr.is_none()
@@ -1877,7 +1877,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         let hir = self.tcx.hir();
         let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
-        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) = node {
+        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, _, body_id), .. }) = node {
             let body = hir.body(*body_id);
             // Point at all the `return`s in the function as they have failed trait bounds.
             let mut visitor = ReturnsVisitor::default();
@@ -4668,7 +4668,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             node: hir::Node<'hir>,
         ) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> {
             match node {
-                hir::Node::Item(item) if let hir::ItemKind::Fn(sig, _, body_id) = item.kind => {
+                hir::Node::Item(item) if let hir::ItemKind::Fn(sig, _, _, body_id) = item.kind => {
                     Some((sig.decl, body_id))
                 }
                 hir::Node::ImplItem(item)
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 5cd10e9053872..faad40fffebd3 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -78,10 +78,10 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
                         if matches!(*orig_lt, ty::ReLateParam(..)) {
                             mapping.insert(
                                 orig_lt,
-                                ty::Region::new_early_param(tcx, ty::EarlyParamRegion {
-                                    index: param.index,
-                                    name: param.name,
-                                }),
+                                ty::Region::new_early_param(
+                                    tcx,
+                                    ty::EarlyParamRegion { index: param.index, name: param.name },
+                                ),
                             );
                         }
                     }
@@ -145,6 +145,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Closure
+        | DefKind::Contract
         | DefKind::SyntheticCoroutineBody => ty::List::empty(),
     }
 }
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 5e2232ff47d73..5e585cbd7bc15 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::{CRATE_HIR_ID, intravisit};
+use rustc_hir::{intravisit, CRATE_HIR_ID};
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
@@ -348,6 +348,7 @@ fn opaque_types_defined_by<'tcx>(
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
+        | DefKind::Contract
         | DefKind::Impl { .. }
         | DefKind::SyntheticCoroutineBody => {}
         // Closures and coroutines are type checked with their parent, so we need to allow all
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 6f1cbb0fee700..3976e659a340a 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -47,6 +47,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
         // Walk over the type behind the alias
         DefKind::TyAlias { .. } | DefKind::AssocTy |
         // Walk over the type of the item
+	DefKind::Contract |
         DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
             if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
                 // If the type of the item uses `_`, we're gonna error out anyway, but
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fa73733360ca1..a633df4a4ffe4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2791,7 +2791,7 @@ fn clean_maybe_renamed_item<'tcx>(
             }
             ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
             // proc macros can have a name set by attributes
-            ItemKind::Fn(ref sig, generics, body_id) => {
+            ItemKind::Fn(ref sig, generics, _, body_id) => {
                 clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
             }
             ItemKind::Trait(_, _, generics, bounds, item_ids) => {
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 383e3135faa86..8d9d9cc6ef7d7 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -163,6 +163,7 @@ impl ItemType {
             | DefKind::GlobalAsm
             | DefKind::Impl { .. }
             | DefKind::Closure
+            | DefKind::Contract
             | DefKind::SyntheticCoroutineBody => Self::ForeignType,
         }
     }
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index b314b060368aa..fcc85e5399f54 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -230,7 +230,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
         match item.kind {
             ItemKind::Static(_, _, _)
             | ItemKind::Const(_, _, _)
-            | ItemKind::Fn(_, _, _)
+            | ItemKind::Fn(_, _, _, _)
             | ItemKind::Macro(_, _)
             | ItemKind::TyAlias(_, _)
             | ItemKind::Enum(_, _)
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index db235786cf49a..da4c4f34d1a12 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1866,6 +1866,7 @@ fn resolution_failure(
                             Variant
                             | Field
                             | Closure
+                            | Contract
                             | AssocTy
                             | AssocConst
                             | AssocFn
diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
index 9b10ae8365149..fded2df706c1b 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
@@ -21,7 +21,7 @@ pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
 }
 
 pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
-    if let ItemKind::Fn(_, _, eid) = item.kind {
+    if let ItemKind::Fn(_, _, _, eid) = item.kind {
         is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
     } else {
         true
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index e090644ae4410..9db5864c4cb2f 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -23,12 +23,12 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_resolve::rustdoc::{
-    DocFragment, add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range,
-    span_of_fragments,
+    add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, span_of_fragments,
+    DocFragment,
 };
 use rustc_session::impl_lint_pass;
 use rustc_span::edition::Edition;
-use rustc_span::{Span, sym};
+use rustc_span::{sym, Span};
 use std::ops::Range;
 use url::Url;
 
@@ -579,7 +579,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation {
                     self.check_private_items,
                 );
                 match item.kind {
-                    ItemKind::Fn(sig, _, body_id) => {
+                    ItemKind::Fn(sig, _, _, body_id) => {
                         if !(is_entrypoint_fn(cx, item.owner_id.to_def_id())
                             || in_external_macro(cx.tcx.sess, item.span))
                         {
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index 6ad879b9fe7ae..b880c4a3ddaad 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::{is_from_proc_macro, trait_ref_of_method};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty};
+use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor};
 use rustc_hir::{
     BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
     PredicateOrigin, Ty, WherePredicate,
@@ -12,8 +12,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
-use rustc_span::Span;
 use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::Span;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -252,7 +252,7 @@ fn is_empty_body(cx: &LateContext<'_>, body: BodyId) -> bool {
 
 impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if let ItemKind::Fn(_, generics, body_id) = item.kind
+        if let ItemKind::Fn(_, generics, _, body_id) = item.kind
             && !generics.params.is_empty()
             && !is_empty_body(cx, body_id)
             && (!self.avoid_breaking_exported_api || !cx.effective_visibilities.is_exported(item.owner_id.def_id))
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index cfd11e9339fb7..c59b87e3a2015 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -8,7 +8,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::{Span, sym};
+use rustc_span::{sym, Span};
 
 use clippy_utils::attrs::is_proc_macro;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
@@ -25,7 +25,7 @@ use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
     let attrs = cx.tcx.hir().attrs(item.hir_id());
     let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
-    if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind {
+    if let hir::ItemKind::Fn(ref sig, _generics, _contracts, ref body_id) = item.kind {
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         if let Some(attr) = attr {
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index d4eaa1663208c..e5f2121663222 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -3,11 +3,11 @@ use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::{Span, sym};
+use rustc_span::{sym, Span};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
-use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_type_diagnostic_item};
+use clippy_utils::ty::{approx_ty_size, is_type_diagnostic_item, AdtVariantInfo};
 
 use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
 
@@ -35,7 +35,7 @@ fn result_err_ty<'tcx>(
 }
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) {
-    if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind
+    if let hir::ItemKind::Fn(ref sig, _generics, _, _) = item.kind
         && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
     {
         if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 4c5375730b8e3..0f804d257b6f6 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -3,18 +3,18 @@ use std::collections::BTreeMap;
 
 use rustc_errors::{Applicability, Diag};
 use rustc_hir as hir;
-use rustc_hir::intravisit::{Visitor, walk_body, walk_expr, walk_inf, walk_ty};
+use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{Ty, TypeckResults};
 use rustc_session::declare_lint_pass;
-use rustc_span::Span;
 use rustc_span::symbol::sym;
+use rustc_span::Span;
 
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::{IntoSpan, SpanRangeExt, snippet};
+use clippy_utils::source::{snippet, IntoSpan, SpanRangeExt};
 use clippy_utils::ty::is_type_diagnostic_item;
 
 declare_clippy_lint! {
@@ -149,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                     );
                 }
             },
-            ItemKind::Fn(ref sig, generics, body_id) => {
+            ItemKind::Fn(ref sig, generics, _, body_id) => {
                 let body = cx.tcx.hir().body(body_id);
 
                 for ty in sig.decl.inputs {
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index ec28671a061e4..174783e786408 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -3,25 +3,25 @@ use clippy_utils::trait_ref_of_method;
 use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::Applicability;
-use rustc_hir::FnRetTy::Return;
 use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
 use rustc_hir::intravisit::{
-    Visitor, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound,
-    walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_where_predicate,
+    walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound, walk_poly_trait_ref,
+    walk_trait_ref, walk_ty, walk_where_predicate, Visitor,
 };
+use rustc_hir::FnRetTy::Return;
 use rustc_hir::{
-    BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics,
-    Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
-    PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate, lang_items,
+    lang_items, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind,
+    Generics, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node,
+    PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter as middle_nested_filter;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
-use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::symbol::{Ident, kw};
+use rustc_span::symbol::{kw, Ident};
+use rustc_span::Span;
 use std::ops::ControlFlow;
 
 declare_clippy_lint! {
@@ -93,7 +93,7 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
 
 impl<'tcx> LateLintPass<'tcx> for Lifetimes {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let ItemKind::Fn(ref sig, generics, id) = item.kind {
+        if let ItemKind::Fn(ref sig, generics, _, id) = item.kind {
             check_fn_inner(cx, sig, Some(id), None, generics, item.span, true);
         } else if let ItemKind::Impl(impl_) = item.kind {
             if !item.span.from_expansion() {
diff --git a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs
index 858e3be5093ef..60db5db766e93 100644
--- a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{fn_def_id, is_from_proc_macro, is_lint_allowed};
-use hir::intravisit::{Visitor, walk_expr};
+use hir::intravisit::{walk_expr, Visitor};
 use hir::{Expr, ExprKind, FnRetTy, FnSig, Node};
 use rustc_ast::Label;
 use rustc_errors::Applicability;
@@ -69,7 +69,7 @@ fn get_parent_fn_ret_ty<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option
     for (_, parent_node) in cx.tcx.hir().parent_iter(expr.hir_id) {
         match parent_node {
             Node::Item(hir::Item {
-                kind: hir::ItemKind::Fn(FnSig { decl, .. }, _, _),
+                kind: hir::ItemKind::Fn(FnSig { decl, .. }, _, _, _),
                 ..
             })
             | Node::TraitItem(hir::TraitItem {
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index cfa1fdb81372f..acfcb0d01fe66 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -2,7 +2,7 @@ use super::implicit_clone::is_clone_like;
 use super::unnecessary_iter_cloned::{self, is_into_iter};
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{SpanRangeExt, snippet};
+use clippy_utils::source::{snippet, SpanRangeExt};
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{
@@ -19,7 +19,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
 use rustc_middle::ty::{
     self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty,
 };
-use rustc_span::{Symbol, sym};
+use rustc_span::{sym, Symbol};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{Obligation, ObligationCause};
 
@@ -496,7 +496,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
             Node::Stmt(_) => return true,
             Node::Block(..) => continue,
             Node::Item(item) => {
-                if let ItemKind::Fn(_, _, body_id) = &item.kind
+                if let ItemKind::Fn(_, _, _, body_id) = &item.kind
                     && let output_ty = return_ty(cx, item.owner_id)
                     && rustc_hir_typeck::can_coerce(cx.tcx, cx.param_env, item.owner_id.def_id, ty, output_ty)
                 {
diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
index d276e29bacecf..c76ffe862e703 100644
--- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
+++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs
@@ -39,7 +39,7 @@ declare_lint_pass!(MultipleBoundLocations => [MULTIPLE_BOUND_LOCATIONS]);
 
 impl EarlyLintPass for MultipleBoundLocations {
     fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) {
-        if let FnKind::Fn(_, _, _, _, generics, _) = kind
+        if let FnKind::Fn(_, _, _, _, generics, _, _) = kind
             && !generics.params.is_empty()
             && !generics.where_clause.predicates.is_empty()
         {
diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
index 8d5a523fd8f6a..cf56a089df429 100644
--- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
+++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -37,7 +37,7 @@ declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]);
 
 impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if let ItemKind::Fn(fn_sig, _, _) = &item.kind {
+        if let ItemKind::Fn(fn_sig, _, _, _) = &item.kind {
             let attrs = cx.tcx.hir().attrs(item.hir_id());
             let mut app = Applicability::MaybeIncorrect;
             let snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut app);
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 565294bb40a82..db6669584067b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -82,7 +82,7 @@ impl Context {
                 }
                 self.const_span = Some(body_span);
             },
-            hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (),
+            hir::BodyOwnerKind::Contract | hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (),
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 662745e4b5d67..16e983fb0599c 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::source::{SpanRangeExt, snippet_with_context};
+use clippy_utils::source::{snippet_with_context, SpanRangeExt};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::visitors::{Descend, for_each_expr, for_each_unconsumed_temporary};
+use clippy_utils::visitors::{for_each_expr, for_each_unconsumed_temporary, Descend};
 use clippy_utils::{
     binary_expr_needs_parentheses, fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res,
     path_to_local_id, span_contains_cfg, span_find_starting_semi,
@@ -9,8 +9,8 @@ use clippy_utils::{
 use core::ops::ControlFlow;
 use rustc_ast::MetaItemInner;
 use rustc_errors::Applicability;
-use rustc_hir::LangItem::ResultErr;
 use rustc_hir::intravisit::FnKind;
+use rustc_hir::LangItem::ResultErr;
 use rustc_hir::{
     Block, Body, Expr, ExprKind, FnDecl, HirId, ItemKind, LangItem, MatchSource, Node, OwnerNode, PatKind, QPath, Stmt,
     StmtKind,
@@ -21,7 +21,7 @@ use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, GenericArgKind, Ty};
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{BytePos, Pos, Span, sym};
+use rustc_span::{sym, BytePos, Pos, Span};
 use std::borrow::Cow;
 use std::fmt::Display;
 
@@ -204,7 +204,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
 
             // Ensure this is not the final stmt, otherwise removing it would cause a compile error
             && let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id))
-            && let ItemKind::Fn(_, _, body) = item.kind
+            && let ItemKind::Fn(_, _, _, body) = item.kind
             && let block = cx.tcx.hir().body(body).value
             && let ExprKind::Block(block, _) = block.kind
             && !is_inside_let_else(cx.tcx, expr)
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 68f74e52ed7b7..d5314372d32db 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.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_contracts(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_contracts(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_contracts(lc, rc)
                 && both(lb.as_ref(), rb.as_ref(), |l, r| eq_block(l, r))
         },
         (
@@ -677,6 +686,20 @@ pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool {
     }
 }
 
+pub fn eq_contracts(l: &FnContract, r: &FnContract) -> bool {
+    let req_cmp = match (&l.requires, &r.requires) {
+        (Some(l_expr), Some(r_expr)) => eq_expr(l_expr, r_expr),
+        (None, None) => true,
+        _ => return false,
+    };
+    let ens_cmp = match (&l.ensures, &r.ensures) {
+        (Some(l_expr), Some(r_expr)) => eq_expr(l_expr, r_expr),
+        (None, None) => true,
+        _ => return false,
+    };
+    req_cmp && ens_cmp
+}
+
 pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool {
     eq_path(&l.prefix, &r.prefix) && eq_use_tree_kind(&l.kind, &r.kind)
 }
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 10e258444a676..33cf4d70317b8 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -77,7 +77,7 @@ pub mod visitors;
 pub use self::attrs::*;
 pub use self::check_proc_macro::{is_from_proc_macro, is_span_if, is_span_match};
 pub use self::hir_utils::{
-    HirEqInterExpr, SpanlessEq, SpanlessHash, both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over,
+    both, count_eq, eq_expr_value, hash_expr, hash_stmt, is_bool, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
 };
 
 use core::mem;
@@ -93,20 +93,20 @@ use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::packed::Pu128;
 use rustc_data_structures::unhash::UnhashMap;
-use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId, LocalModDefId};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalModDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefPath, DefPathData};
 use rustc_hir::hir_id::{HirIdMap, HirIdSet};
-use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
+use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
+use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::{
-    self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
-    Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
-    ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
-    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
-    TyKind, UnOp, def,
+    self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind,
+    ConstContext, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem,
+    ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode,
+    Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef,
+    TraitRef, TyKind, UnOp,
 };
-use rustc_lexer::{TokenKind, tokenize};
+use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::mir::Const;
@@ -119,12 +119,12 @@ use rustc_middle::ty::{
 };
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{Ident, Symbol, kw};
-use rustc_span::{InnerSpan, Span, sym};
+use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::{sym, InnerSpan, Span};
 use rustc_target::abi::Integer;
 use visitors::Visitable;
 
-use crate::consts::{ConstEvalCtxt, Constant, mir_to_const};
+use crate::consts::{mir_to_const, ConstEvalCtxt, Constant};
 use crate::higher::Range;
 use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
 use crate::visitors::for_each_expr_without_closures;
@@ -1400,7 +1400,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
     enclosing_node.and_then(|node| match node {
         Node::Block(block) => Some(block),
         Node::Item(&Item {
-            kind: ItemKind::Fn(_, _, eid),
+            kind: ItemKind::Fn(_, _, _, eid),
             ..
         })
         | Node::ImplItem(&ImplItem {
@@ -2609,7 +2609,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
             // function scope
             .any(|(_id, node)| {
                 if let Node::Item(item) = node {
-                    if let ItemKind::Fn(_, _, _) = item.kind {
+                    if let ItemKind::Fn(_, _, _, _) = item.kind {
                         // Note that we have sorted the item names in the visitor,
                         // so the binary_search gets the same as `contains`, but faster.
                         return names.binary_search(&item.ident.name).is_ok();
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index fc043a697e039..63647f812765f 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -333,12 +333,12 @@ impl<'a> FnSig<'a> {
         defaultness: ast::Defaultness,
     ) -> FnSig<'a> {
         match *fn_kind {
-            visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, fn_sig, vis, generics, _) => {
+            visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, fn_sig, vis, generics, _, _) => {
                 let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis);
                 fn_sig.defaultness = defaultness;
                 fn_sig
             }
-            visit::FnKind::Fn(_, _, fn_sig, vis, generics, _) => FnSig {
+            visit::FnKind::Fn(_, _, fn_sig, vis, generics, _, _) => FnSig {
                 decl,
                 generics,
                 ext: fn_sig.header.ext,
@@ -3432,6 +3432,7 @@ impl Rewrite for ast::ForeignItem {
                     defaultness,
                     ref sig,
                     ref generics,
+                    ref contract,
                     ref body,
                 } = **fn_kind;
                 if let Some(ref body) = body {
@@ -3447,6 +3448,7 @@ impl Rewrite for ast::ForeignItem {
                             sig,
                             &self.vis,
                             generics,
+                            contract,
                             Some(body),
                         ),
                         &sig.decl,
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 8102fe7ad8f29..b0d2f45d79b91 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -386,7 +386,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         let indent = self.block_indent;
         let block;
         let rewrite = match fk {
-            visit::FnKind::Fn(_, ident, _, _, _, Some(ref b)) => {
+            visit::FnKind::Fn(_, ident, _, _, _, _, Some(ref b)) => {
                 block = b;
                 self.rewrite_fn_before_block(
                     indent,
@@ -538,6 +538,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         defaultness,
                         ref sig,
                         ref generics,
+                        ref contract,
                         ref body,
                     } = **fn_kind;
                     if let Some(ref body) = body {
@@ -553,6 +554,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                                 sig,
                                 &item.vis,
                                 generics,
+                                contract,
                                 Some(body),
                             ),
                             &sig.decl,
@@ -646,13 +648,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     defaultness,
                     ref sig,
                     ref generics,
+                    ref contract,
                     ref body,
                 } = **fn_kind;
                 if let Some(ref body) = body {
                     let inner_attrs = inner_attributes(&ai.attrs);
                     let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
                     self.visit_fn(
-                        visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, generics, Some(body)),
+                        visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, generics, contract, Some(body)),
                         &sig.decl,
                         ai.span,
                         defaultness,