about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-01-28 12:56:04 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-09-23 13:34:09 +0000
commit286502c9ed77e49aea5bb89cf18c5eda3a8fce92 (patch)
tree08a01a16ddcbb97325f70ff0677debf33c332065
parenta626caaad97b7f8733b8c9bd1fe9662cfc1e3ec1 (diff)
downloadrust-286502c9ed77e49aea5bb89cf18c5eda3a8fce92.tar.gz
rust-286502c9ed77e49aea5bb89cf18c5eda3a8fce92.zip
Enable drop_tracking_mir by default.
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs601
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs92
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs96
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs306
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs242
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs723
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs6
-rw-r--r--compiler/rustc_interface/src/passes.rs14
-rw-r--r--compiler/rustc_interface/src/tests.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs19
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs21
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs7
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs70
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs107
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs4
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs191
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs43
29 files changed, 114 insertions, 2513 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 116222ba56e..564206f9e4b 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1579,13 +1579,7 @@ fn opaque_type_cycle_error(
                         label_match(capture.place.ty(), capture.get_path_span(tcx));
                     }
                     // Label any generator locals that capture the opaque
-                    for interior_ty in
-                        typeck_results.generator_interior_types.as_ref().skip_binder()
-                    {
-                        label_match(interior_ty.ty, interior_ty.span);
-                    }
-                    if tcx.sess.opts.unstable_opts.drop_tracking_mir
-                        && let DefKind::Generator = tcx.def_kind(closure_def_id)
+                    if let DefKind::Generator = tcx.def_kind(closure_def_id)
                         && let Some(generator_layout) = tcx.mir_generator_witnesses(closure_def_id)
                     {
                         for interior_ty in &generator_layout.field_tys {
@@ -1603,7 +1597,6 @@ fn opaque_type_cycle_error(
 }
 
 pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    debug_assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
     debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Generator));
 
     let typeck = tcx.typeck(def_id);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index fea726ff8ca..e32f45b4224 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -510,25 +510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
-        if self.tcx.sess.opts.unstable_opts.drop_tracking_mir {
-            self.save_generator_interior_predicates(def_id);
-            return;
-        }
-
-        self.select_obligations_where_possible(|_| {});
-
-        let mut generators = self.deferred_generator_interiors.borrow_mut();
-        for (generator_def_id, body_id, interior, kind) in generators.drain(..) {
-            crate::generator_interior::resolve_interior(
-                self,
-                def_id,
-                generator_def_id,
-                body_id,
-                interior,
-                kind,
-            );
-            self.select_obligations_where_possible(|_| {});
-        }
+        self.save_generator_interior_predicates(def_id);
     }
 
     /// Unify the inference variables corresponding to generator witnesses, and save all the
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
deleted file mode 100644
index cfedcee9956..00000000000
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ /dev/null
@@ -1,601 +0,0 @@
-use super::{
-    for_each_consumable, record_consumed_borrow::ConsumedAndBorrowedPlaces, DropRangesBuilder,
-    NodeInfo, PostOrderId, TrackedValue, TrackedValueIndex,
-};
-use hir::{
-    intravisit::{self, Visitor},
-    Body, Expr, ExprKind, Guard, HirId, LoopIdError,
-};
-use rustc_data_structures::unord::{UnordMap, UnordSet};
-use rustc_hir as hir;
-use rustc_index::IndexVec;
-use rustc_infer::infer::InferCtxt;
-use rustc_middle::{
-    hir::map::Map,
-    ty::{ParamEnv, TyCtxt, TypeVisitableExt, TypeckResults},
-};
-use std::mem::swap;
-
-/// Traverses the body to find the control flow graph and locations for the
-/// relevant places are dropped or reinitialized.
-///
-/// The resulting structure still needs to be iterated to a fixed point, which
-/// can be done with propagate_to_fixpoint in cfg_propagate.
-pub(super) fn build_control_flow_graph<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    typeck_results: &TypeckResults<'tcx>,
-    param_env: ParamEnv<'tcx>,
-    consumed_borrowed_places: ConsumedAndBorrowedPlaces,
-    body: &'tcx Body<'tcx>,
-    num_exprs: usize,
-) -> (DropRangesBuilder, UnordSet<HirId>) {
-    let mut drop_range_visitor = DropRangeVisitor::new(
-        infcx,
-        typeck_results,
-        param_env,
-        consumed_borrowed_places,
-        num_exprs,
-    );
-    intravisit::walk_body(&mut drop_range_visitor, body);
-
-    drop_range_visitor.drop_ranges.process_deferred_edges();
-    if let Some(filename) = &infcx.tcx.sess.opts.unstable_opts.dump_drop_tracking_cfg {
-        super::cfg_visualize::write_graph_to_file(
-            &drop_range_visitor.drop_ranges,
-            filename,
-            infcx.tcx,
-        );
-    }
-
-    (drop_range_visitor.drop_ranges, drop_range_visitor.places.borrowed_temporaries)
-}
-
-/// This struct is used to gather the information for `DropRanges` to determine the regions of the
-/// HIR tree for which a value is dropped.
-///
-/// We are interested in points where a variables is dropped or initialized, and the control flow
-/// of the code. We identify locations in code by their post-order traversal index, so it is
-/// important for this traversal to match that in `RegionResolutionVisitor` and `InteriorVisitor`.
-///
-/// We make several simplifying assumptions, with the goal of being more conservative than
-/// necessary rather than less conservative (since being less conservative is unsound, but more
-/// conservative is still safe). These assumptions are:
-///
-/// 1. Moving a variable `a` counts as a move of the whole variable.
-/// 2. Moving a partial path like `a.b.c` is ignored.
-/// 3. Reinitializing through a field (e.g. `a.b.c = 5`) counts as a reinitialization of all of
-///    `a`.
-///
-/// Some examples:
-///
-/// Rule 1:
-/// ```rust
-/// let mut a = (vec![0], vec![0]);
-/// drop(a);
-/// // `a` is not considered initialized.
-/// ```
-///
-/// Rule 2:
-/// ```rust
-/// let mut a = (vec![0], vec![0]);
-/// drop(a.0);
-/// drop(a.1);
-/// // `a` is still considered initialized.
-/// ```
-///
-/// Rule 3:
-/// ```compile_fail,E0382
-/// let mut a = (vec![0], vec![0]);
-/// drop(a);
-/// a.1 = vec![1];
-/// // all of `a` is considered initialized
-/// ```
-
-struct DropRangeVisitor<'a, 'tcx> {
-    typeck_results: &'a TypeckResults<'tcx>,
-    infcx: &'a InferCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
-    places: ConsumedAndBorrowedPlaces,
-    drop_ranges: DropRangesBuilder,
-    expr_index: PostOrderId,
-    label_stack: Vec<(Option<rustc_ast::Label>, PostOrderId)>,
-}
-
-impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
-    fn new(
-        infcx: &'a InferCtxt<'tcx>,
-        typeck_results: &'a TypeckResults<'tcx>,
-        param_env: ParamEnv<'tcx>,
-        places: ConsumedAndBorrowedPlaces,
-        num_exprs: usize,
-    ) -> Self {
-        debug!("consumed_places: {:?}", places.consumed);
-        let drop_ranges = DropRangesBuilder::new(
-            places.consumed.iter().flat_map(|(_, places)| places.iter().cloned()),
-            infcx.tcx.hir(),
-            num_exprs,
-        );
-        Self {
-            infcx,
-            typeck_results,
-            param_env,
-            places,
-            drop_ranges,
-            expr_index: PostOrderId::from_u32(0),
-            label_stack: vec![],
-        }
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
-    }
-
-    fn record_drop(&mut self, value: TrackedValue) {
-        if self.places.borrowed.contains(&value) {
-            debug!("not marking {:?} as dropped because it is borrowed at some point", value);
-        } else {
-            debug!("marking {:?} as dropped at {:?}", value, self.expr_index);
-            let count = self.expr_index;
-            self.drop_ranges.drop_at(value, count);
-        }
-    }
-
-    /// ExprUseVisitor's consume callback doesn't go deep enough for our purposes in all
-    /// expressions. This method consumes a little deeper into the expression when needed.
-    fn consume_expr(&mut self, expr: &hir::Expr<'_>) {
-        debug!("consuming expr {:?}, count={:?}", expr.kind, self.expr_index);
-        let places = self
-            .places
-            .consumed
-            .get(&expr.hir_id)
-            .map_or(vec![], |places| places.iter().cloned().collect());
-        for place in places {
-            trace!(?place, "consuming place");
-            for_each_consumable(self.tcx().hir(), place, |value| self.record_drop(value));
-        }
-    }
-
-    /// Marks an expression as being reinitialized.
-    ///
-    /// Note that we always approximated on the side of things being more
-    /// initialized than they actually are, as opposed to less. In cases such
-    /// as `x.y = ...`, we would consider all of `x` as being initialized
-    /// instead of just the `y` field.
-    ///
-    /// This is because it is always safe to consider something initialized
-    /// even when it is not, but the other way around will cause problems.
-    ///
-    /// In the future, we will hopefully tighten up these rules to be more
-    /// precise.
-    fn reinit_expr(&mut self, expr: &hir::Expr<'_>) {
-        // Walk the expression to find the base. For example, in an expression
-        // like `*a[i].x`, we want to find the `a` and mark that as
-        // reinitialized.
-        match expr.kind {
-            ExprKind::Path(hir::QPath::Resolved(
-                _,
-                hir::Path { res: hir::def::Res::Local(hir_id), .. },
-            )) => {
-                // This is the base case, where we have found an actual named variable.
-
-                let location = self.expr_index;
-                debug!("reinitializing {:?} at {:?}", hir_id, location);
-                self.drop_ranges.reinit_at(TrackedValue::Variable(*hir_id), location);
-            }
-
-            ExprKind::Field(base, _) => self.reinit_expr(base),
-
-            // Most expressions do not refer to something where we need to track
-            // reinitializations.
-            //
-            // Some of these may be interesting in the future
-            ExprKind::Path(..)
-            | ExprKind::ConstBlock(..)
-            | ExprKind::Array(..)
-            | ExprKind::Call(..)
-            | ExprKind::MethodCall(..)
-            | ExprKind::Tup(..)
-            | ExprKind::Binary(..)
-            | ExprKind::Unary(..)
-            | ExprKind::Lit(..)
-            | ExprKind::Cast(..)
-            | ExprKind::Type(..)
-            | ExprKind::DropTemps(..)
-            | ExprKind::Let(..)
-            | ExprKind::If(..)
-            | ExprKind::Loop(..)
-            | ExprKind::Match(..)
-            | ExprKind::Closure { .. }
-            | ExprKind::Block(..)
-            | ExprKind::Assign(..)
-            | ExprKind::AssignOp(..)
-            | ExprKind::Index(..)
-            | ExprKind::AddrOf(..)
-            | ExprKind::Break(..)
-            | ExprKind::Continue(..)
-            | ExprKind::Ret(..)
-            | ExprKind::Become(..)
-            | ExprKind::InlineAsm(..)
-            | ExprKind::OffsetOf(..)
-            | ExprKind::Struct(..)
-            | ExprKind::Repeat(..)
-            | ExprKind::Yield(..)
-            | ExprKind::Err(_) => (),
-        }
-    }
-
-    /// For an expression with an uninhabited return type (e.g. a function that returns !),
-    /// this adds a self edge to the CFG to model the fact that the function does not
-    /// return.
-    fn handle_uninhabited_return(&mut self, expr: &Expr<'tcx>) {
-        let ty = self.typeck_results.expr_ty(expr);
-        let ty = self.infcx.resolve_vars_if_possible(ty);
-        if ty.has_non_region_infer() {
-            self.tcx()
-                .sess
-                .delay_span_bug(expr.span, format!("could not resolve infer vars in `{ty}`"));
-            return;
-        }
-        let ty = self.tcx().erase_regions(ty);
-        let m = self.tcx().parent_module(expr.hir_id).to_def_id();
-        if !ty.is_inhabited_from(self.tcx(), m, self.param_env) {
-            // This function will not return. We model this fact as an infinite loop.
-            self.drop_ranges.add_control_edge(self.expr_index + 1, self.expr_index + 1);
-        }
-    }
-
-    /// Map a Destination to an equivalent expression node
-    ///
-    /// The destination field of a Break or Continue expression can target either an
-    /// expression or a block. The drop range analysis, however, only deals in
-    /// expression nodes, so blocks that might be the destination of a Break or Continue
-    /// will not have a PostOrderId.
-    ///
-    /// If the destination is an expression, this function will simply return that expression's
-    /// hir_id. If the destination is a block, this function will return the hir_id of last
-    /// expression in the block.
-    fn find_target_expression_from_destination(
-        &self,
-        destination: hir::Destination,
-    ) -> Result<HirId, LoopIdError> {
-        destination.target_id.map(|target| {
-            let node = self.tcx().hir().get(target);
-            match node {
-                hir::Node::Expr(_) => target,
-                hir::Node::Block(b) => find_last_block_expression(b),
-                hir::Node::Param(..)
-                | hir::Node::Item(..)
-                | hir::Node::ForeignItem(..)
-                | hir::Node::TraitItem(..)
-                | hir::Node::ImplItem(..)
-                | hir::Node::Variant(..)
-                | hir::Node::Field(..)
-                | hir::Node::AnonConst(..)
-                | hir::Node::ConstBlock(..)
-                | hir::Node::Stmt(..)
-                | hir::Node::PathSegment(..)
-                | hir::Node::Ty(..)
-                | hir::Node::TypeBinding(..)
-                | hir::Node::TraitRef(..)
-                | hir::Node::Pat(..)
-                | hir::Node::PatField(..)
-                | hir::Node::ExprField(..)
-                | hir::Node::Arm(..)
-                | hir::Node::Local(..)
-                | hir::Node::Ctor(..)
-                | hir::Node::Lifetime(..)
-                | hir::Node::GenericParam(..)
-                | hir::Node::Crate(..)
-                | hir::Node::Infer(..) => bug!("Unsupported branch target: {:?}", node),
-            }
-        })
-    }
-}
-
-fn find_last_block_expression(block: &hir::Block<'_>) -> HirId {
-    block.expr.map_or_else(
-        // If there is no tail expression, there will be at least one statement in the
-        // block because the block contains a break or continue statement.
-        || block.stmts.last().unwrap().hir_id,
-        |expr| expr.hir_id,
-    )
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        let mut reinit = None;
-        match expr.kind {
-            ExprKind::Assign(lhs, rhs, _) => {
-                self.visit_expr(rhs);
-                self.visit_expr(lhs);
-
-                reinit = Some(lhs);
-            }
-
-            ExprKind::If(test, if_true, if_false) => {
-                self.visit_expr(test);
-
-                let fork = self.expr_index;
-
-                self.drop_ranges.add_control_edge(fork, self.expr_index + 1);
-                self.visit_expr(if_true);
-                let true_end = self.expr_index;
-
-                self.drop_ranges.add_control_edge(fork, self.expr_index + 1);
-                if let Some(if_false) = if_false {
-                    self.visit_expr(if_false);
-                }
-
-                self.drop_ranges.add_control_edge(true_end, self.expr_index + 1);
-            }
-            ExprKind::Match(scrutinee, arms, ..) => {
-                // We walk through the match expression almost like a chain of if expressions.
-                // Here's a diagram to follow along with:
-                //
-                //           ┌─┐
-                //     match │A│ {
-                //       ┌───┴─┘
-                //       │
-                //      ┌▼┌───►┌─┐   ┌─┐
-                //      │B│ if │C│ =>│D│,
-                //      └─┘    ├─┴──►└─┴──────┐
-                //          ┌──┘              │
-                //       ┌──┘                 │
-                //       │                    │
-                //      ┌▼┌───►┌─┐   ┌─┐      │
-                //      │E│ if │F│ =>│G│,     │
-                //      └─┘    ├─┴──►└─┴┐     │
-                //             │        │     │
-                //     }       ▼        ▼     │
-                //     ┌─┐◄───────────────────┘
-                //     │H│
-                //     └─┘
-                //
-                // The order we want is that the scrutinee (A) flows into the first pattern (B),
-                // which flows into the guard (C). Then the guard either flows into the arm body
-                // (D) or into the start of the next arm (E). Finally, the body flows to the end
-                // of the match block (H).
-                //
-                // The subsequent arms follow the same ordering. First we go to the pattern, then
-                // the guard (if present, otherwise it flows straight into the body), then into
-                // the body and then to the end of the match expression.
-                //
-                // The comments below show which edge is being added.
-                self.visit_expr(scrutinee);
-
-                let (guard_exit, arm_end_ids) = arms.iter().fold(
-                    (self.expr_index, vec![]),
-                    |(incoming_edge, mut arm_end_ids), hir::Arm { pat, body, guard, .. }| {
-                        // A -> B, or C -> E
-                        self.drop_ranges.add_control_edge(incoming_edge, self.expr_index + 1);
-                        self.visit_pat(pat);
-                        // B -> C and E -> F are added implicitly due to the traversal order.
-                        match guard {
-                            Some(Guard::If(expr)) => self.visit_expr(expr),
-                            Some(Guard::IfLet(let_expr)) => {
-                                self.visit_let_expr(let_expr);
-                            }
-                            None => (),
-                        }
-                        // Likewise, C -> D and F -> G are added implicitly.
-
-                        // Save C, F, so we can add the other outgoing edge.
-                        let to_next_arm = self.expr_index;
-
-                        // The default edge does not get added since we also have an explicit edge,
-                        // so we also need to add an edge to the next node as well.
-                        //
-                        // This adds C -> D, F -> G
-                        self.drop_ranges.add_control_edge(self.expr_index, self.expr_index + 1);
-                        self.visit_expr(body);
-
-                        // Save the end of the body so we can add the exit edge once we know where
-                        // the exit is.
-                        arm_end_ids.push(self.expr_index);
-
-                        // Pass C to the next iteration, as well as vec![D]
-                        //
-                        // On the last round through, we pass F and vec![D, G] so that we can
-                        // add all the exit edges.
-                        (to_next_arm, arm_end_ids)
-                    },
-                );
-                // F -> H
-                self.drop_ranges.add_control_edge(guard_exit, self.expr_index + 1);
-
-                arm_end_ids.into_iter().for_each(|arm_end| {
-                    // D -> H, G -> H
-                    self.drop_ranges.add_control_edge(arm_end, self.expr_index + 1)
-                });
-            }
-
-            ExprKind::Loop(body, label, ..) => {
-                let loop_begin = self.expr_index + 1;
-                self.label_stack.push((label, loop_begin));
-                if body.stmts.is_empty() && body.expr.is_none() {
-                    // For empty loops we won't have updated self.expr_index after visiting the
-                    // body, meaning we'd get an edge from expr_index to expr_index + 1, but
-                    // instead we want an edge from expr_index + 1 to expr_index + 1.
-                    self.drop_ranges.add_control_edge(loop_begin, loop_begin);
-                } else {
-                    self.visit_block(body);
-                    self.drop_ranges.add_control_edge(self.expr_index, loop_begin);
-                }
-                self.label_stack.pop();
-            }
-            // Find the loop entry by searching through the label stack for either the last entry
-            // (if label is none), or the first entry where the label matches this one. The Loop
-            // case maintains this stack mapping labels to the PostOrderId for the loop entry.
-            ExprKind::Continue(hir::Destination { label, .. }, ..) => self
-                .label_stack
-                .iter()
-                .rev()
-                .find(|(loop_label, _)| label.is_none() || *loop_label == label)
-                .map_or((), |(_, target)| {
-                    self.drop_ranges.add_control_edge(self.expr_index, *target)
-                }),
-
-            ExprKind::Break(destination, value) => {
-                // destination either points to an expression or to a block. We use
-                // find_target_expression_from_destination to use the last expression of the block
-                // if destination points to a block.
-                //
-                // We add an edge to the hir_id of the expression/block we are breaking out of, and
-                // then in process_deferred_edges we will map this hir_id to its PostOrderId, which
-                // will refer to the end of the block due to the post order traversal.
-                if let Ok(target) = self.find_target_expression_from_destination(destination) {
-                    self.drop_ranges.add_control_edge_hir_id(self.expr_index, target)
-                }
-
-                if let Some(value) = value {
-                    self.visit_expr(value);
-                }
-            }
-
-            ExprKind::Become(_call) => bug!("encountered a tail-call inside a generator"),
-
-            ExprKind::Call(f, args) => {
-                self.visit_expr(f);
-                for arg in args {
-                    self.visit_expr(arg);
-                }
-
-                self.handle_uninhabited_return(expr);
-            }
-            ExprKind::MethodCall(_, receiver, exprs, _) => {
-                self.visit_expr(receiver);
-                for expr in exprs {
-                    self.visit_expr(expr);
-                }
-
-                self.handle_uninhabited_return(expr);
-            }
-
-            ExprKind::AddrOf(..)
-            | ExprKind::Array(..)
-            // FIXME(eholk): We probably need special handling for AssignOps. The ScopeTree builder
-            // in region.rs runs both lhs then rhs and rhs then lhs and then sets all yields to be
-            // the latest they show up in either traversal. With the older scope-based
-            // approximation, this was fine, but it's probably not right now. What we probably want
-            // to do instead is still run both orders, but consider anything that showed up as a
-            // yield in either order.
-            | ExprKind::AssignOp(..)
-            | ExprKind::Binary(..)
-            | ExprKind::Block(..)
-            | ExprKind::Cast(..)
-            | ExprKind::Closure { .. }
-            | ExprKind::ConstBlock(..)
-            | ExprKind::DropTemps(..)
-            | ExprKind::Err(_)
-            | ExprKind::Field(..)
-            | ExprKind::Index(..)
-            | ExprKind::InlineAsm(..)
-            | ExprKind::OffsetOf(..)
-            | ExprKind::Let(..)
-            | ExprKind::Lit(..)
-            | ExprKind::Path(..)
-            | ExprKind::Repeat(..)
-            | ExprKind::Ret(..)
-            | ExprKind::Struct(..)
-            | ExprKind::Tup(..)
-            | ExprKind::Type(..)
-            | ExprKind::Unary(..)
-            | ExprKind::Yield(..) => intravisit::walk_expr(self, expr),
-        }
-
-        self.expr_index = self.expr_index + 1;
-        self.drop_ranges.add_node_mapping(expr.hir_id, self.expr_index);
-        self.consume_expr(expr);
-        if let Some(expr) = reinit {
-            self.reinit_expr(expr);
-        }
-    }
-
-    fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
-        intravisit::walk_pat(self, pat);
-
-        // Increment expr_count here to match what InteriorVisitor expects.
-        self.expr_index = self.expr_index + 1;
-
-        // Save a node mapping to get better CFG visualization
-        self.drop_ranges.add_node_mapping(pat.hir_id, self.expr_index);
-    }
-}
-
-impl DropRangesBuilder {
-    fn new(
-        tracked_values: impl Iterator<Item = TrackedValue>,
-        hir: Map<'_>,
-        num_exprs: usize,
-    ) -> Self {
-        let mut tracked_value_map = UnordMap::<_, TrackedValueIndex>::default();
-        let mut next = <_>::from(0u32);
-        for value in tracked_values {
-            for_each_consumable(hir, value, |value| {
-                if let std::collections::hash_map::Entry::Vacant(e) = tracked_value_map.entry(value)
-                {
-                    e.insert(next);
-                    next = next + 1;
-                }
-            });
-        }
-        debug!("hir_id_map: {:#?}", tracked_value_map);
-        let num_values = tracked_value_map.len();
-        Self {
-            tracked_value_map,
-            nodes: IndexVec::from_fn_n(|_| NodeInfo::new(num_values), num_exprs + 1),
-            deferred_edges: <_>::default(),
-            post_order_map: <_>::default(),
-        }
-    }
-
-    fn tracked_value_index(&self, tracked_value: TrackedValue) -> TrackedValueIndex {
-        *self.tracked_value_map.get(&tracked_value).unwrap()
-    }
-
-    /// Adds an entry in the mapping from HirIds to PostOrderIds
-    ///
-    /// Needed so that `add_control_edge_hir_id` can work.
-    fn add_node_mapping(&mut self, node_hir_id: HirId, post_order_id: PostOrderId) {
-        self.post_order_map.insert(node_hir_id, post_order_id);
-    }
-
-    /// Like add_control_edge, but uses a hir_id as the target.
-    ///
-    /// This can be used for branches where we do not know the PostOrderId of the target yet,
-    /// such as when handling `break` or `continue`.
-    fn add_control_edge_hir_id(&mut self, from: PostOrderId, to: HirId) {
-        self.deferred_edges.push((from, to));
-    }
-
-    fn drop_at(&mut self, value: TrackedValue, location: PostOrderId) {
-        let value = self.tracked_value_index(value);
-        self.node_mut(location).drops.push(value);
-    }
-
-    fn reinit_at(&mut self, value: TrackedValue, location: PostOrderId) {
-        let value = match self.tracked_value_map.get(&value) {
-            Some(value) => *value,
-            // If there's no value, this is never consumed and therefore is never dropped. We can
-            // ignore this.
-            None => return,
-        };
-        self.node_mut(location).reinits.push(value);
-    }
-
-    /// Looks up PostOrderId for any control edges added by HirId and adds a proper edge for them.
-    ///
-    /// Should be called after visiting the HIR but before solving the control flow, otherwise some
-    /// edges will be missed.
-    fn process_deferred_edges(&mut self) {
-        trace!("processing deferred edges. post_order_map={:#?}", self.post_order_map);
-        let mut edges = vec![];
-        swap(&mut edges, &mut self.deferred_edges);
-        edges.into_iter().for_each(|(from, to)| {
-            trace!("Adding deferred edge from {:?} to {:?}", from, to);
-            let to = *self.post_order_map.get(&to).expect("Expression ID not found");
-            trace!("target edge PostOrderId={:?}", to);
-            self.add_control_edge(from, to)
-        });
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs
deleted file mode 100644
index 633b478895b..00000000000
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-use super::{DropRangesBuilder, PostOrderId};
-use rustc_index::{bit_set::BitSet, IndexVec};
-use std::collections::BTreeMap;
-
-impl DropRangesBuilder {
-    pub fn propagate_to_fixpoint(&mut self) {
-        trace!("before fixpoint: {:#?}", self);
-        let preds = self.compute_predecessors();
-
-        trace!("predecessors: {:#?}", preds.iter_enumerated().collect::<BTreeMap<_, _>>());
-
-        let mut new_state = BitSet::new_empty(self.num_values());
-        let mut changed_nodes = BitSet::new_empty(self.nodes.len());
-        let mut unchanged_mask = BitSet::new_filled(self.nodes.len());
-        changed_nodes.insert(0u32.into());
-
-        let mut propagate = || {
-            let mut changed = false;
-            unchanged_mask.insert_all();
-            for id in self.nodes.indices() {
-                trace!("processing {:?}, changed_nodes: {:?}", id, changed_nodes);
-                // Check if any predecessor has changed, and if not then short-circuit.
-                //
-                // We handle the start node specially, since it doesn't have any predecessors,
-                // but we need to start somewhere.
-                if match id.index() {
-                    0 => !changed_nodes.contains(id),
-                    _ => !preds[id].iter().any(|pred| changed_nodes.contains(*pred)),
-                } {
-                    trace!("short-circuiting because none of {:?} have changed", preds[id]);
-                    unchanged_mask.remove(id);
-                    continue;
-                }
-
-                if id.index() == 0 {
-                    new_state.clear();
-                } else {
-                    // If we are not the start node and we have no predecessors, treat
-                    // everything as dropped because there's no way to get here anyway.
-                    new_state.insert_all();
-                };
-
-                for pred in &preds[id] {
-                    new_state.intersect(&self.nodes[*pred].drop_state);
-                }
-
-                for drop in &self.nodes[id].drops {
-                    new_state.insert(*drop);
-                }
-
-                for reinit in &self.nodes[id].reinits {
-                    new_state.remove(*reinit);
-                }
-
-                if self.nodes[id].drop_state.intersect(&new_state) {
-                    changed_nodes.insert(id);
-                    changed = true;
-                } else {
-                    unchanged_mask.remove(id);
-                }
-            }
-
-            changed_nodes.intersect(&unchanged_mask);
-            changed
-        };
-
-        while propagate() {
-            trace!("drop_state changed, re-running propagation");
-        }
-
-        trace!("after fixpoint: {:#?}", self);
-    }
-
-    fn compute_predecessors(&self) -> IndexVec<PostOrderId, Vec<PostOrderId>> {
-        let mut preds = IndexVec::from_fn_n(|_| vec![], self.nodes.len());
-        for (id, node) in self.nodes.iter_enumerated() {
-            // If the node has no explicit successors, we assume that control
-            // will from this node into the next one.
-            //
-            // If there are successors listed, then we assume that all
-            // possible successors are given and we do not include the default.
-            if node.successors.len() == 0 && id.index() != self.nodes.len() - 1 {
-                preds[id + 1].push(id);
-            } else {
-                for succ in &node.successors {
-                    preds[*succ].push(id);
-                }
-            }
-        }
-        preds
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
deleted file mode 100644
index e8d31be79d9..00000000000
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-//! Implementation of GraphWalk for DropRanges so we can visualize the control
-//! flow graph when needed for debugging.
-
-use rustc_graphviz as dot;
-use rustc_hir::{Expr, ExprKind, Node};
-use rustc_middle::ty::TyCtxt;
-
-use super::{DropRangesBuilder, PostOrderId};
-
-/// Writes the CFG for DropRangesBuilder to a .dot file for visualization.
-///
-/// It is not normally called, but is kept around to easily add debugging
-/// code when needed.
-pub(super) fn write_graph_to_file(
-    drop_ranges: &DropRangesBuilder,
-    filename: &str,
-    tcx: TyCtxt<'_>,
-) {
-    dot::render(
-        &DropRangesGraph { drop_ranges, tcx },
-        &mut std::fs::File::create(filename).unwrap(),
-    )
-    .unwrap();
-}
-
-struct DropRangesGraph<'a, 'tcx> {
-    drop_ranges: &'a DropRangesBuilder,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl<'a> dot::GraphWalk<'a> for DropRangesGraph<'_, '_> {
-    type Node = PostOrderId;
-
-    type Edge = (PostOrderId, PostOrderId);
-
-    fn nodes(&'a self) -> dot::Nodes<'a, Self::Node> {
-        self.drop_ranges.nodes.iter_enumerated().map(|(i, _)| i).collect()
-    }
-
-    fn edges(&'a self) -> dot::Edges<'a, Self::Edge> {
-        self.drop_ranges
-            .nodes
-            .iter_enumerated()
-            .flat_map(|(i, node)| {
-                if node.successors.len() == 0 {
-                    vec![(i, i + 1)]
-                } else {
-                    node.successors.iter().map(move |&s| (i, s)).collect()
-                }
-            })
-            .collect()
-    }
-
-    fn source(&'a self, edge: &Self::Edge) -> Self::Node {
-        edge.0
-    }
-
-    fn target(&'a self, edge: &Self::Edge) -> Self::Node {
-        edge.1
-    }
-}
-
-impl<'a> dot::Labeller<'a> for DropRangesGraph<'_, '_> {
-    type Node = PostOrderId;
-
-    type Edge = (PostOrderId, PostOrderId);
-
-    fn graph_id(&'a self) -> dot::Id<'a> {
-        dot::Id::new("drop_ranges").unwrap()
-    }
-
-    fn node_id(&'a self, n: &Self::Node) -> dot::Id<'a> {
-        dot::Id::new(format!("id{}", n.index())).unwrap()
-    }
-
-    fn node_label(&'a self, n: &Self::Node) -> dot::LabelText<'a> {
-        dot::LabelText::LabelStr(
-            format!(
-                "{n:?}: {}",
-                self.drop_ranges
-                    .post_order_map
-                    .iter()
-                    .find(|(_hir_id, &post_order_id)| post_order_id == *n)
-                    .map_or("<unknown>".into(), |(hir_id, _)| format!(
-                        "{}{}",
-                        self.tcx.hir().node_to_string(*hir_id),
-                        match self.tcx.hir().find(*hir_id) {
-                            Some(Node::Expr(Expr { kind: ExprKind::Yield(..), .. })) => " (yield)",
-                            _ => "",
-                        }
-                    ))
-            )
-            .into(),
-        )
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
deleted file mode 100644
index e563bd40b65..00000000000
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
+++ /dev/null
@@ -1,306 +0,0 @@
-//! Drop range analysis finds the portions of the tree where a value is guaranteed to be dropped
-//! (i.e. moved, uninitialized, etc.). This is used to exclude the types of those values from the
-//! generator type. See `InteriorVisitor::record` for where the results of this analysis are used.
-//!
-//! There are three phases to this analysis:
-//! 1. Use `ExprUseVisitor` to identify the interesting values that are consumed and borrowed.
-//! 2. Use `DropRangeVisitor` to find where the interesting values are dropped or reinitialized,
-//!    and also build a control flow graph.
-//! 3. Use `DropRanges::propagate_to_fixpoint` to flow the dropped/reinitialized information through
-//!    the CFG and find the exact points where we know a value is definitely dropped.
-//!
-//! The end result is a data structure that maps the post-order index of each node in the HIR tree
-//! to a set of values that are known to be dropped at that location.
-
-use self::cfg_build::build_control_flow_graph;
-use self::record_consumed_borrow::find_consumed_and_borrowed;
-use crate::FnCtxt;
-use hir::def_id::DefId;
-use hir::{Body, HirId, HirIdMap, Node};
-use rustc_data_structures::unord::{UnordMap, UnordSet};
-use rustc_hir as hir;
-use rustc_index::bit_set::BitSet;
-use rustc_index::IndexVec;
-use rustc_middle::hir::map::Map;
-use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId};
-use rustc_middle::ty;
-use std::collections::BTreeMap;
-use std::fmt::Debug;
-
-mod cfg_build;
-mod cfg_propagate;
-mod cfg_visualize;
-mod record_consumed_borrow;
-
-pub fn compute_drop_ranges<'a, 'tcx>(
-    fcx: &'a FnCtxt<'a, 'tcx>,
-    def_id: DefId,
-    body: &'tcx Body<'tcx>,
-) -> DropRanges {
-    if fcx.sess().opts.unstable_opts.drop_tracking {
-        let consumed_borrowed_places = find_consumed_and_borrowed(fcx, def_id, body);
-
-        let typeck_results = &fcx.typeck_results.borrow();
-        let num_exprs = fcx.tcx.region_scope_tree(def_id).body_expr_count(body.id()).unwrap_or(0);
-        let (mut drop_ranges, borrowed_temporaries) = build_control_flow_graph(
-            &fcx,
-            typeck_results,
-            fcx.param_env,
-            consumed_borrowed_places,
-            body,
-            num_exprs,
-        );
-
-        drop_ranges.propagate_to_fixpoint();
-
-        debug!("borrowed_temporaries = {borrowed_temporaries:?}");
-        DropRanges {
-            tracked_value_map: drop_ranges.tracked_value_map,
-            nodes: drop_ranges.nodes,
-            borrowed_temporaries: Some(borrowed_temporaries),
-        }
-    } else {
-        // If drop range tracking is not enabled, skip all the analysis and produce an
-        // empty set of DropRanges.
-        DropRanges {
-            tracked_value_map: UnordMap::default(),
-            nodes: IndexVec::new(),
-            borrowed_temporaries: None,
-        }
-    }
-}
-
-/// Applies `f` to consumable node in the HIR subtree pointed to by `place`.
-///
-/// This includes the place itself, and if the place is a reference to a local
-/// variable then `f` is also called on the HIR node for that variable as well.
-///
-/// For example, if `place` points to `foo()`, then `f` is called once for the
-/// result of `foo`. On the other hand, if `place` points to `x` then `f` will
-/// be called both on the `ExprKind::Path` node that represents the expression
-/// as well as the HirId of the local `x` itself.
-fn for_each_consumable(hir: Map<'_>, place: TrackedValue, mut f: impl FnMut(TrackedValue)) {
-    f(place);
-    let node = hir.find(place.hir_id());
-    if let Some(Node::Expr(expr)) = node {
-        match expr.kind {
-            hir::ExprKind::Path(hir::QPath::Resolved(
-                _,
-                hir::Path { res: hir::def::Res::Local(hir_id), .. },
-            )) => {
-                f(TrackedValue::Variable(*hir_id));
-            }
-            _ => (),
-        }
-    }
-}
-
-rustc_index::newtype_index! {
-    #[debug_format = "id({})"]
-    pub struct PostOrderId {}
-}
-
-rustc_index::newtype_index! {
-    #[debug_format = "hidx({})"]
-    pub struct TrackedValueIndex {}
-}
-
-/// Identifies a value whose drop state we need to track.
-#[derive(PartialEq, Eq, Hash, Clone, Copy)]
-enum TrackedValue {
-    /// Represents a named variable, such as a let binding, parameter, or upvar.
-    ///
-    /// The HirId points to the variable's definition site.
-    Variable(HirId),
-    /// A value produced as a result of an expression.
-    ///
-    /// The HirId points to the expression that returns this value.
-    Temporary(HirId),
-}
-
-impl Debug for TrackedValue {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        ty::tls::with_opt(|opt_tcx| {
-            if let Some(tcx) = opt_tcx {
-                write!(f, "{}", tcx.hir().node_to_string(self.hir_id()))
-            } else {
-                match self {
-                    Self::Variable(hir_id) => write!(f, "Variable({hir_id:?})"),
-                    Self::Temporary(hir_id) => write!(f, "Temporary({hir_id:?})"),
-                }
-            }
-        })
-    }
-}
-
-impl TrackedValue {
-    fn hir_id(&self) -> HirId {
-        match self {
-            TrackedValue::Variable(hir_id) | TrackedValue::Temporary(hir_id) => *hir_id,
-        }
-    }
-
-    fn from_place_with_projections_allowed(place_with_id: &PlaceWithHirId<'_>) -> Self {
-        match place_with_id.place.base {
-            PlaceBase::Rvalue | PlaceBase::StaticItem => {
-                TrackedValue::Temporary(place_with_id.hir_id)
-            }
-            PlaceBase::Local(hir_id)
-            | PlaceBase::Upvar(ty::UpvarId { var_path: ty::UpvarPath { hir_id }, .. }) => {
-                TrackedValue::Variable(hir_id)
-            }
-        }
-    }
-}
-
-/// Represents a reason why we might not be able to convert a HirId or Place
-/// into a tracked value.
-#[derive(Debug)]
-enum TrackedValueConversionError {
-    /// Place projects are not currently supported.
-    ///
-    /// The reasoning around these is kind of subtle, so we choose to be more
-    /// conservative around these for now. There is no reason in theory we
-    /// cannot support these, we just have not implemented it yet.
-    PlaceProjectionsNotSupported,
-}
-
-impl TryFrom<&PlaceWithHirId<'_>> for TrackedValue {
-    type Error = TrackedValueConversionError;
-
-    fn try_from(place_with_id: &PlaceWithHirId<'_>) -> Result<Self, Self::Error> {
-        if !place_with_id.place.projections.is_empty() {
-            debug!(
-                "TrackedValue from PlaceWithHirId: {:?} has projections, which are not supported.",
-                place_with_id
-            );
-            return Err(TrackedValueConversionError::PlaceProjectionsNotSupported);
-        }
-
-        Ok(TrackedValue::from_place_with_projections_allowed(place_with_id))
-    }
-}
-
-pub struct DropRanges {
-    tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
-    nodes: IndexVec<PostOrderId, NodeInfo>,
-    borrowed_temporaries: Option<UnordSet<HirId>>,
-}
-
-impl DropRanges {
-    pub fn is_dropped_at(&self, hir_id: HirId, location: usize) -> bool {
-        self.tracked_value_map
-            .get(&TrackedValue::Temporary(hir_id))
-            .or(self.tracked_value_map.get(&TrackedValue::Variable(hir_id)))
-            .cloned()
-            .is_some_and(|tracked_value_id| {
-                self.expect_node(location.into()).drop_state.contains(tracked_value_id)
-            })
-    }
-
-    pub fn is_borrowed_temporary(&self, expr: &hir::Expr<'_>) -> bool {
-        if let Some(b) = &self.borrowed_temporaries { b.contains(&expr.hir_id) } else { true }
-    }
-
-    /// Returns a reference to the NodeInfo for a node, panicking if it does not exist
-    fn expect_node(&self, id: PostOrderId) -> &NodeInfo {
-        &self.nodes[id]
-    }
-}
-
-/// Tracks information needed to compute drop ranges.
-struct DropRangesBuilder {
-    /// The core of DropRangesBuilder is a set of nodes, which each represent
-    /// one expression. We primarily refer to them by their index in a
-    /// post-order traversal of the HIR tree,  since this is what
-    /// generator_interior uses to talk about yield positions.
-    ///
-    /// This IndexVec keeps the relevant details for each node. See the
-    /// NodeInfo struct for more details, but this information includes things
-    /// such as the set of control-flow successors, which variables are dropped
-    /// or reinitialized, and whether each variable has been inferred to be
-    /// known-dropped or potentially reinitialized at each point.
-    nodes: IndexVec<PostOrderId, NodeInfo>,
-    /// We refer to values whose drop state we are tracking by the HirId of
-    /// where they are defined. Within a NodeInfo, however, we store the
-    /// drop-state in a bit vector indexed by a HirIdIndex
-    /// (see NodeInfo::drop_state). The hir_id_map field stores the mapping
-    /// from HirIds to the HirIdIndex that is used to represent that value in
-    /// bitvector.
-    tracked_value_map: UnordMap<TrackedValue, TrackedValueIndex>,
-
-    /// When building the control flow graph, we don't always know the
-    /// post-order index of the target node at the point we encounter it.
-    /// For example, this happens with break and continue. In those cases,
-    /// we store a pair of the PostOrderId of the source and the HirId
-    /// of the target. Once we have gathered all of these edges, we make a
-    /// pass over the set of deferred edges (see process_deferred_edges in
-    /// cfg_build.rs), look up the PostOrderId for the target (since now the
-    /// post-order index for all nodes is known), and add missing control flow
-    /// edges.
-    deferred_edges: Vec<(PostOrderId, HirId)>,
-    /// This maps HirIds of expressions to their post-order index. It is
-    /// used in process_deferred_edges to correctly add back-edges.
-    post_order_map: HirIdMap<PostOrderId>,
-}
-
-impl Debug for DropRangesBuilder {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        f.debug_struct("DropRanges")
-            .field("hir_id_map", &self.tracked_value_map)
-            .field("post_order_maps", &self.post_order_map)
-            .field("nodes", &self.nodes.iter_enumerated().collect::<BTreeMap<_, _>>())
-            .finish()
-    }
-}
-
-/// DropRanges keeps track of what values are definitely dropped at each point in the code.
-///
-/// Values of interest are defined by the hir_id of their place. Locations in code are identified
-/// by their index in the post-order traversal. At its core, DropRanges maps
-/// (hir_id, post_order_id) -> bool, where a true value indicates that the value is definitely
-/// dropped at the point of the node identified by post_order_id.
-impl DropRangesBuilder {
-    /// Returns the number of values (hir_ids) that are tracked
-    fn num_values(&self) -> usize {
-        self.tracked_value_map.len()
-    }
-
-    fn node_mut(&mut self, id: PostOrderId) -> &mut NodeInfo {
-        let size = self.num_values();
-        self.nodes.ensure_contains_elem(id, || NodeInfo::new(size))
-    }
-
-    fn add_control_edge(&mut self, from: PostOrderId, to: PostOrderId) {
-        trace!("adding control edge from {:?} to {:?}", from, to);
-        self.node_mut(from).successors.push(to);
-    }
-}
-
-#[derive(Debug)]
-struct NodeInfo {
-    /// IDs of nodes that can follow this one in the control flow
-    ///
-    /// If the vec is empty, then control proceeds to the next node.
-    successors: Vec<PostOrderId>,
-
-    /// List of hir_ids that are dropped by this node.
-    drops: Vec<TrackedValueIndex>,
-
-    /// List of hir_ids that are reinitialized by this node.
-    reinits: Vec<TrackedValueIndex>,
-
-    /// Set of values that are definitely dropped at this point.
-    drop_state: BitSet<TrackedValueIndex>,
-}
-
-impl NodeInfo {
-    fn new(num_values: usize) -> Self {
-        Self {
-            successors: vec![],
-            drops: vec![],
-            reinits: vec![],
-            drop_state: BitSet::new_filled(num_values),
-        }
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
deleted file mode 100644
index 29413f08012..00000000000
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
+++ /dev/null
@@ -1,242 +0,0 @@
-use super::TrackedValue;
-use crate::{
-    expr_use_visitor::{self, ExprUseVisitor},
-    FnCtxt,
-};
-use hir::{def_id::DefId, Body, HirId, HirIdMap};
-use rustc_data_structures::{fx::FxIndexSet, unord::UnordSet};
-use rustc_hir as hir;
-use rustc_middle::ty::{ParamEnv, TyCtxt};
-use rustc_middle::{
-    hir::place::{PlaceBase, Projection, ProjectionKind},
-    ty::TypeVisitableExt,
-};
-
-pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
-    fcx: &'a FnCtxt<'a, 'tcx>,
-    def_id: DefId,
-    body: &'tcx Body<'tcx>,
-) -> ConsumedAndBorrowedPlaces {
-    let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx, fcx.param_env);
-    expr_use_visitor.consume_body(fcx, def_id, body);
-    expr_use_visitor.places
-}
-
-pub(super) struct ConsumedAndBorrowedPlaces {
-    /// Records the variables/expressions that are dropped by a given expression.
-    ///
-    /// The key is the hir-id of the expression, and the value is a set or hir-ids for variables
-    /// or values that are consumed by that expression.
-    ///
-    /// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is
-    /// not considered a drop of `x`, although it would be a drop of `x.y`.
-    pub(super) consumed: HirIdMap<FxIndexSet<TrackedValue>>,
-
-    /// A set of hir-ids of values or variables that are borrowed at some point within the body.
-    pub(super) borrowed: UnordSet<TrackedValue>,
-
-    /// A set of hir-ids of values or variables that are borrowed at some point within the body.
-    pub(super) borrowed_temporaries: UnordSet<HirId>,
-}
-
-/// Works with ExprUseVisitor to find interesting values for the drop range analysis.
-///
-/// Interesting values are those that are either dropped or borrowed. For dropped values, we also
-/// record the parent expression, which is the point where the drop actually takes place.
-struct ExprUseDelegate<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    param_env: ParamEnv<'tcx>,
-    places: ConsumedAndBorrowedPlaces,
-}
-
-impl<'tcx> ExprUseDelegate<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
-        Self {
-            tcx,
-            param_env,
-            places: ConsumedAndBorrowedPlaces {
-                consumed: <_>::default(),
-                borrowed: <_>::default(),
-                borrowed_temporaries: <_>::default(),
-            },
-        }
-    }
-
-    fn consume_body(&mut self, fcx: &'_ FnCtxt<'_, 'tcx>, def_id: DefId, body: &'tcx Body<'tcx>) {
-        // Run ExprUseVisitor to find where values are consumed.
-        ExprUseVisitor::new(
-            self,
-            &fcx.infcx,
-            def_id.expect_local(),
-            fcx.param_env,
-            &fcx.typeck_results.borrow(),
-        )
-        .consume_body(body);
-    }
-
-    fn mark_consumed(&mut self, consumer: HirId, target: TrackedValue) {
-        self.places.consumed.entry(consumer).or_insert_with(|| <_>::default());
-
-        debug!(?consumer, ?target, "mark_consumed");
-        self.places.consumed.get_mut(&consumer).map(|places| places.insert(target));
-    }
-
-    fn borrow_place(&mut self, place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>) {
-        self.places
-            .borrowed
-            .insert(TrackedValue::from_place_with_projections_allowed(place_with_id));
-
-        // Ordinarily a value is consumed by it's parent, but in the special case of a
-        // borrowed RValue, we create a reference that lives as long as the temporary scope
-        // for that expression (typically, the innermost statement, but sometimes the enclosing
-        // block). We record this fact here so that later in generator_interior
-        // we can use the correct scope.
-        //
-        // We special case borrows through a dereference (`&*x`, `&mut *x` where `x` is
-        // some rvalue expression), since these are essentially a copy of a pointer.
-        // In other words, this borrow does not refer to the
-        // temporary (`*x`), but to the referent (whatever `x` is a borrow of).
-        //
-        // We were considering that we might encounter problems down the line if somehow,
-        // some part of the compiler were to look at this result and try to use it to
-        // drive a borrowck-like analysis (this does not currently happen, as of this writing).
-        // But even this should be fine, because the lifetime of the dereferenced reference
-        // found in the rvalue is only significant as an intermediate 'link' to the value we
-        // are producing, and we separately track whether that value is live over a yield.
-        // Example:
-        //
-        // ```notrust
-        // fn identity<T>(x: &mut T) -> &mut T { x }
-        // let a: A = ...;
-        // let y: &'y mut A = &mut *identity(&'a mut a);
-        //                    ^^^^^^^^^^^^^^^^^^^^^^^^^ the borrow we are talking about
-        // ```
-        //
-        // The expression `*identity(...)` is a deref of an rvalue,
-        // where the `identity(...)` (the rvalue) produces a return type
-        // of `&'rv mut A`, where `'a: 'rv`. We then assign this result to
-        // `'y`, resulting in (transitively) `'a: 'y` (i.e., while `y` is in use,
-        // `a` will be considered borrowed). Other parts of the code will ensure
-        // that if `y` is live over a yield, `&'y mut A` appears in the generator
-        // state. If `'y` is live, then any sound region analysis must conclude
-        // that `'a` is also live. So if this causes a bug, blame some other
-        // part of the code!
-        let is_deref = place_with_id
-            .place
-            .projections
-            .iter()
-            .any(|Projection { kind, .. }| *kind == ProjectionKind::Deref);
-
-        if let (false, PlaceBase::Rvalue) = (is_deref, place_with_id.place.base) {
-            self.places.borrowed_temporaries.insert(place_with_id.hir_id);
-        }
-    }
-}
-
-impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
-    fn consume(
-        &mut self,
-        place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
-        diag_expr_id: HirId,
-    ) {
-        let hir = self.tcx.hir();
-        let parent = match hir.opt_parent_id(place_with_id.hir_id) {
-            Some(parent) => parent,
-            None => place_with_id.hir_id,
-        };
-        debug!(
-            "consume {:?}; diag_expr_id={}, using parent {}",
-            place_with_id,
-            hir.node_to_string(diag_expr_id),
-            hir.node_to_string(parent)
-        );
-
-        if let Ok(tracked_value) = place_with_id.try_into() {
-            self.mark_consumed(parent, tracked_value)
-        }
-    }
-
-    fn borrow(
-        &mut self,
-        place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
-        diag_expr_id: HirId,
-        bk: rustc_middle::ty::BorrowKind,
-    ) {
-        debug!(
-            "borrow: place_with_id = {place_with_id:#?}, diag_expr_id={diag_expr_id:#?}, \
-            borrow_kind={bk:#?}"
-        );
-
-        self.borrow_place(place_with_id);
-    }
-
-    fn copy(
-        &mut self,
-        place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
-        _diag_expr_id: HirId,
-    ) {
-        debug!("copy: place_with_id = {place_with_id:?}");
-
-        self.places
-            .borrowed
-            .insert(TrackedValue::from_place_with_projections_allowed(place_with_id));
-
-        // For copied we treat this mostly like a borrow except that we don't add the place
-        // to borrowed_temporaries because the copy is consumed.
-    }
-
-    fn mutate(
-        &mut self,
-        assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
-        diag_expr_id: HirId,
-    ) {
-        debug!("mutate {assignee_place:?}; diag_expr_id={diag_expr_id:?}");
-
-        if assignee_place.place.base == PlaceBase::Rvalue
-            && assignee_place.place.projections.is_empty()
-        {
-            // Assigning to an Rvalue is illegal unless done through a dereference. We would have
-            // already gotten a type error, so we will just return here.
-            return;
-        }
-
-        // If the type being assigned needs dropped, then the mutation counts as a borrow
-        // since it is essentially doing `Drop::drop(&mut x); x = new_value;`.
-        let ty = self.tcx.erase_regions(assignee_place.place.base_ty);
-        if ty.has_infer() {
-            self.tcx.sess.delay_span_bug(
-                self.tcx.hir().span(assignee_place.hir_id),
-                format!("inference variables in {ty}"),
-            );
-        } else if ty.needs_drop(self.tcx, self.param_env) {
-            self.places
-                .borrowed
-                .insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
-        }
-    }
-
-    fn bind(
-        &mut self,
-        binding_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
-        diag_expr_id: HirId,
-    ) {
-        debug!("bind {binding_place:?}; diag_expr_id={diag_expr_id:?}");
-    }
-
-    fn fake_read(
-        &mut self,
-        place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
-        cause: rustc_middle::mir::FakeReadCause,
-        diag_expr_id: HirId,
-    ) {
-        debug!(
-            "fake_read place_with_id={place_with_id:?}; cause={cause:?}; diag_expr_id={diag_expr_id:?}"
-        );
-
-        // fake reads happen in places like the scrutinee of a match expression.
-        // we treat those as a borrow, much like a copy: the idea is that we are
-        // transiently creating a `&T` ref that we can read from to observe the current
-        // value (this `&T` is immediately dropped afterwards).
-        self.borrow_place(place_with_id);
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
deleted file mode 100644
index d2ab5aa6bae..00000000000
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ /dev/null
@@ -1,723 +0,0 @@
-//! This calculates the types which has storage which lives across a suspension point in a
-//! generator from the perspective of typeck. The actual types used at runtime
-//! is calculated in `rustc_mir_transform::generator` and may be a subset of the
-//! types computed here.
-
-use self::drop_ranges::DropRanges;
-use super::FnCtxt;
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_errors::{pluralize, DelayDm};
-use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::hir_id::HirIdSet;
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
-use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin};
-use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::symbol::sym;
-use rustc_span::Span;
-use smallvec::{smallvec, SmallVec};
-
-mod drop_ranges;
-
-struct InteriorVisitor<'a, 'tcx> {
-    fcx: &'a FnCtxt<'a, 'tcx>,
-    region_scope_tree: &'a region::ScopeTree,
-    types: FxIndexSet<ty::GeneratorInteriorTypeCause<'tcx>>,
-    rvalue_scopes: &'a RvalueScopes,
-    expr_count: usize,
-    kind: hir::GeneratorKind,
-    prev_unresolved_span: Option<Span>,
-    linted_values: HirIdSet,
-    drop_ranges: DropRanges,
-}
-
-impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
-    fn record(
-        &mut self,
-        ty: Ty<'tcx>,
-        hir_id: HirId,
-        scope: Option<region::Scope>,
-        expr: Option<&'tcx Expr<'tcx>>,
-        source_span: Span,
-    ) {
-        use rustc_span::DUMMY_SP;
-
-        let ty = self.fcx.resolve_vars_if_possible(ty);
-
-        debug!(
-            "attempting to record type ty={:?}; hir_id={:?}; scope={:?}; expr={:?}; source_span={:?}; expr_count={:?}",
-            ty, hir_id, scope, expr, source_span, self.expr_count,
-        );
-
-        let live_across_yield = scope
-            .map(|s| {
-                self.region_scope_tree.yield_in_scope(s).and_then(|yield_data| {
-                    // If we are recording an expression that is the last yield
-                    // in the scope, or that has a postorder CFG index larger
-                    // than the one of all of the yields, then its value can't
-                    // be storage-live (and therefore live) at any of the yields.
-                    //
-                    // See the mega-comment at `yield_in_scope` for a proof.
-
-                    yield_data
-                        .iter()
-                        .find(|yield_data| {
-                            debug!(
-                                "comparing counts yield: {} self: {}, source_span = {:?}",
-                                yield_data.expr_and_pat_count, self.expr_count, source_span
-                            );
-
-                            if self
-                                .is_dropped_at_yield_location(hir_id, yield_data.expr_and_pat_count)
-                            {
-                                debug!("value is dropped at yield point; not recording");
-                                return false;
-                            }
-
-                            // If it is a borrowing happening in the guard,
-                            // it needs to be recorded regardless because they
-                            // do live across this yield point.
-                            yield_data.expr_and_pat_count >= self.expr_count
-                        })
-                        .cloned()
-                })
-            })
-            .unwrap_or_else(|| {
-                Some(YieldData { span: DUMMY_SP, expr_and_pat_count: 0, source: self.kind.into() })
-            });
-
-        if let Some(yield_data) = live_across_yield {
-            debug!(
-                "type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}",
-                expr, scope, ty, self.expr_count, yield_data.span
-            );
-
-            if let Some((unresolved_term, unresolved_type_span)) =
-                self.fcx.first_unresolved_const_or_ty_var(&ty)
-            {
-                // If unresolved type isn't a ty_var then unresolved_type_span is None
-                let span = self
-                    .prev_unresolved_span
-                    .unwrap_or_else(|| unresolved_type_span.unwrap_or(source_span));
-
-                // If we encounter an int/float variable, then inference fallback didn't
-                // finish due to some other error. Don't emit spurious additional errors.
-                if let Some(unresolved_ty) = unresolved_term.ty()
-                    && let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) = unresolved_ty.kind()
-                {
-                    self.fcx
-                        .tcx
-                        .sess
-                        .delay_span_bug(span, format!("Encountered var {unresolved_term:?}"));
-                } else {
-                    let note = format!(
-                        "the type is part of the {} because of this {}",
-                        self.kind.descr(),
-                        yield_data.source
-                    );
-
-                    self.fcx
-                        .need_type_info_err_in_generator(self.kind, span, unresolved_term)
-                        .span_note(yield_data.span, note)
-                        .emit();
-                }
-            } else {
-                // Insert the type into the ordered set.
-                let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree));
-
-                if !self.linted_values.contains(&hir_id) {
-                    check_must_not_suspend_ty(
-                        self.fcx,
-                        ty,
-                        hir_id,
-                        SuspendCheckData {
-                            expr,
-                            source_span,
-                            yield_span: yield_data.span,
-                            plural_len: 1,
-                            ..Default::default()
-                        },
-                    );
-                    self.linted_values.insert(hir_id);
-                }
-
-                self.types.insert(ty::GeneratorInteriorTypeCause {
-                    span: source_span,
-                    ty,
-                    scope_span,
-                    yield_span: yield_data.span,
-                    expr: expr.map(|e| e.hir_id),
-                });
-            }
-        } else {
-            debug!(
-                "no type in expr = {:?}, count = {:?}, span = {:?}",
-                expr,
-                self.expr_count,
-                expr.map(|e| e.span)
-            );
-            if let Some((unresolved_type, unresolved_type_span)) =
-                self.fcx.first_unresolved_const_or_ty_var(&ty)
-            {
-                debug!(
-                    "remained unresolved_type = {:?}, unresolved_type_span: {:?}",
-                    unresolved_type, unresolved_type_span
-                );
-                self.prev_unresolved_span = unresolved_type_span;
-            }
-        }
-    }
-
-    /// If drop tracking is enabled, consult drop_ranges to see if a value is
-    /// known to be dropped at a yield point and therefore can be omitted from
-    /// the generator witness.
-    fn is_dropped_at_yield_location(&self, value_hir_id: HirId, yield_location: usize) -> bool {
-        // short-circuit if drop tracking is not enabled.
-        if !self.fcx.sess().opts.unstable_opts.drop_tracking {
-            return false;
-        }
-
-        self.drop_ranges.is_dropped_at(value_hir_id, yield_location)
-    }
-}
-
-pub fn resolve_interior<'a, 'tcx>(
-    fcx: &'a FnCtxt<'a, 'tcx>,
-    def_id: DefId,
-    generator_def_id: LocalDefId,
-    body_id: hir::BodyId,
-    interior: Ty<'tcx>,
-    kind: hir::GeneratorKind,
-) {
-    let body = fcx.tcx.hir().body(body_id);
-    let typeck_results = fcx.inh.typeck_results.borrow();
-    let mut visitor = InteriorVisitor {
-        fcx,
-        types: FxIndexSet::default(),
-        region_scope_tree: fcx.tcx.region_scope_tree(def_id),
-        rvalue_scopes: &typeck_results.rvalue_scopes,
-        expr_count: 0,
-        kind,
-        prev_unresolved_span: None,
-        linted_values: <_>::default(),
-        drop_ranges: drop_ranges::compute_drop_ranges(fcx, def_id, body),
-    };
-    intravisit::walk_body(&mut visitor, body);
-
-    // Check that we visited the same amount of expressions as the RegionResolutionVisitor
-    let region_expr_count = fcx.tcx.region_scope_tree(def_id).body_expr_count(body_id).unwrap();
-    assert_eq!(region_expr_count, visitor.expr_count);
-
-    // The types are already kept in insertion order.
-    let types = visitor.types;
-
-    if fcx.tcx.features().unsized_locals || fcx.tcx.features().unsized_fn_params {
-        for interior_ty in &types {
-            fcx.require_type_is_sized(
-                interior_ty.ty,
-                interior_ty.span,
-                ObligationCauseCode::SizedGeneratorInterior(generator_def_id),
-            );
-        }
-    }
-
-    // The types in the generator interior contain lifetimes local to the generator itself,
-    // which should not be exposed outside of the generator. Therefore, we replace these
-    // lifetimes with existentially-bound lifetimes, which reflect the exact value of the
-    // lifetimes not being known by users.
-    //
-    // These lifetimes are used in auto trait impl checking (for example,
-    // if a Sync generator contains an &'α T, we need to check whether &'α T: Sync),
-    // so knowledge of the exact relationships between them isn't particularly important.
-
-    debug!("types in generator {:?}, span = {:?}", types, body.value.span);
-
-    // We want to deduplicate if the lifetimes are the same modulo some non-informative counter.
-    // So, we need to actually do two passes: first by type to anonymize (preserving information
-    // required for diagnostics), then a second pass over all captured types to reassign disjoint
-    // region indices.
-    let mut captured_tys = FxHashSet::default();
-    let type_causes: Vec<_> = types
-        .into_iter()
-        .filter_map(|mut cause| {
-            // Replace all regions inside the generator interior with late bound regions.
-            // Note that each region slot in the types gets a new fresh late bound region,
-            // which means that none of the regions inside relate to any other, even if
-            // typeck had previously found constraints that would cause them to be related.
-
-            let mut counter = 0;
-            let mut mk_bound_region = |kind| {
-                let var = ty::BoundVar::from_u32(counter);
-                counter += 1;
-                ty::BoundRegion { var, kind }
-            };
-            let ty = fcx.normalize(cause.span, cause.ty);
-            let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
-                let br = match region.kind() {
-                    ty::ReVar(vid) => {
-                        let origin = fcx.region_var_origin(vid);
-                        match origin {
-                            RegionVariableOrigin::EarlyBoundRegion(span, _) => {
-                                mk_bound_region(ty::BrAnon(Some(span)))
-                            }
-                            _ => mk_bound_region(ty::BrAnon(None)),
-                        }
-                    }
-                    ty::ReEarlyBound(region) => {
-                        mk_bound_region(ty::BrNamed(region.def_id, region.name))
-                    }
-                    ty::ReLateBound(_, ty::BoundRegion { kind, .. })
-                    | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
-                        ty::BoundRegionKind::BrAnon(span) => mk_bound_region(ty::BrAnon(span)),
-                        ty::BoundRegionKind::BrNamed(def_id, sym) => {
-                            mk_bound_region(ty::BrNamed(def_id, sym))
-                        }
-                        ty::BoundRegionKind::BrEnv => mk_bound_region(ty::BrAnon(None)),
-                    },
-                    _ => mk_bound_region(ty::BrAnon(None)),
-                };
-                let r = ty::Region::new_late_bound(fcx.tcx, current_depth, br);
-                r
-            });
-            captured_tys.insert(ty).then(|| {
-                cause.ty = ty;
-                cause
-            })
-        })
-        .collect();
-
-    let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![];
-    let mut counter = 0;
-    // Optimization: If there is only one captured type, then we don't actually
-    // need to fold and reindex (since the first type doesn't change).
-    let type_causes = if captured_tys.len() > 0 {
-        // Optimization: Use `replace_escaping_bound_vars_uncached` instead of
-        // `fold_regions`, since we only have late bound regions, and it skips
-        // types without bound regions.
-        fcx.tcx.replace_escaping_bound_vars_uncached(
-            type_causes,
-            FnMutDelegate {
-                regions: &mut |br| {
-                    let kind = br.kind;
-                    let var = ty::BoundVar::from_usize(bound_vars.len());
-                    bound_vars.push(ty::BoundVariableKind::Region(kind));
-                    counter += 1;
-                    ty::Region::new_late_bound(
-                        fcx.tcx,
-                        ty::INNERMOST,
-                        ty::BoundRegion { var, kind },
-                    )
-                },
-                types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
-                consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
-            },
-        )
-    } else {
-        type_causes
-    };
-
-    // Extract type components to build the witness type.
-    let type_list = fcx.tcx.mk_type_list_from_iter(type_causes.iter().map(|cause| cause.ty));
-    let bound_vars = fcx.tcx.mk_bound_variable_kinds(&bound_vars);
-    let witness =
-        Ty::new_generator_witness(fcx.tcx, ty::Binder::bind_with_vars(type_list, bound_vars));
-
-    drop(typeck_results);
-    // Store the generator types and spans into the typeck results for this generator.
-    fcx.inh.typeck_results.borrow_mut().generator_interior_types =
-        ty::Binder::bind_with_vars(type_causes, bound_vars);
-
-    debug!(
-        "types in generator after region replacement {:?}, span = {:?}",
-        witness, body.value.span
-    );
-
-    // Unify the type variable inside the generator with the new witness
-    match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(
-        DefineOpaqueTypes::No,
-        interior,
-        witness,
-    ) {
-        Ok(ok) => fcx.register_infer_ok_obligations(ok),
-        _ => bug!("failed to relate {interior} and {witness}"),
-    }
-}
-
-// This visitor has to have the same visit_expr calls as RegionResolutionVisitor in
-// librustc_middle/middle/region.rs since `expr_count` is compared against the results
-// there.
-impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
-    fn visit_arm(&mut self, arm: &'tcx Arm<'tcx>) {
-        let Arm { guard, pat, body, .. } = arm;
-        self.visit_pat(pat);
-        if let Some(ref g) = guard {
-            {
-                // If there is a guard, we need to count all variables bound in the pattern as
-                // borrowed for the entire guard body, regardless of whether they are accessed.
-                // We do this by walking the pattern bindings and recording `&T` for any `x: T`
-                // that is bound.
-
-                struct ArmPatCollector<'a, 'b, 'tcx> {
-                    interior_visitor: &'a mut InteriorVisitor<'b, 'tcx>,
-                    scope: Scope,
-                }
-
-                impl<'a, 'b, 'tcx> Visitor<'tcx> for ArmPatCollector<'a, 'b, 'tcx> {
-                    fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
-                        intravisit::walk_pat(self, pat);
-                        if let PatKind::Binding(_, id, ident, ..) = pat.kind {
-                            let ty =
-                                self.interior_visitor.fcx.typeck_results.borrow().node_type(id);
-                            let tcx = self.interior_visitor.fcx.tcx;
-                            let ty = Ty::new_ref(
-                                tcx,
-                                // Use `ReErased` as `resolve_interior` is going to replace all the
-                                // regions anyway.
-                                tcx.lifetimes.re_erased,
-                                ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
-                            );
-                            self.interior_visitor.record(
-                                ty,
-                                id,
-                                Some(self.scope),
-                                None,
-                                ident.span,
-                            );
-                        }
-                    }
-                }
-
-                ArmPatCollector {
-                    interior_visitor: self,
-                    scope: Scope { id: g.body().hir_id.local_id, data: ScopeData::Node },
-                }
-                .visit_pat(pat);
-            }
-
-            match g {
-                Guard::If(ref e) => {
-                    self.visit_expr(e);
-                }
-                Guard::IfLet(ref l) => {
-                    self.visit_let_expr(l);
-                }
-            }
-        }
-        self.visit_expr(body);
-    }
-
-    fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
-        intravisit::walk_pat(self, pat);
-
-        self.expr_count += 1;
-
-        if let PatKind::Binding(..) = pat.kind {
-            let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
-            let ty = self.fcx.typeck_results.borrow().pat_ty(pat);
-            self.record(ty, pat.hir_id, Some(scope), None, pat.span);
-        }
-    }
-
-    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        match &expr.kind {
-            ExprKind::Call(callee, args) => match &callee.kind {
-                ExprKind::Path(qpath) => {
-                    let res = self.fcx.typeck_results.borrow().qpath_res(qpath, callee.hir_id);
-                    match res {
-                        // Direct calls never need to keep the callee `ty::FnDef`
-                        // ZST in a temporary, so skip its type, just in case it
-                        // can significantly complicate the generator type.
-                        Res::Def(
-                            DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn),
-                            _,
-                        ) => {
-                            // NOTE(eddyb) this assumes a path expression has
-                            // no nested expressions to keep track of.
-                            self.expr_count += 1;
-
-                            // Record the rest of the call expression normally.
-                            for arg in *args {
-                                self.visit_expr(arg);
-                            }
-                        }
-                        _ => intravisit::walk_expr(self, expr),
-                    }
-                }
-                _ => intravisit::walk_expr(self, expr),
-            },
-            _ => intravisit::walk_expr(self, expr),
-        }
-
-        self.expr_count += 1;
-
-        debug!("is_borrowed_temporary: {:?}", self.drop_ranges.is_borrowed_temporary(expr));
-
-        let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr);
-
-        // Typically, the value produced by an expression is consumed by its parent in some way,
-        // so we only have to check if the parent contains a yield (note that the parent may, for
-        // example, store the value into a local variable, but then we already consider local
-        // variables to be live across their scope).
-        //
-        // However, in the case of temporary values, we are going to store the value into a
-        // temporary on the stack that is live for the current temporary scope and then return a
-        // reference to it. That value may be live across the entire temporary scope.
-        //
-        // There's another subtlety: if the type has an observable drop, it must be dropped after
-        // the yield, even if it's not borrowed or referenced after the yield. Ideally this would
-        // *only* happen for types with observable drop, not all types which wrap them, but that
-        // doesn't match the behavior of MIR borrowck and causes ICEs. See the FIXME comment in
-        // tests/ui/generator/drop-tracking-parent-expression.rs.
-        let scope = if self.drop_ranges.is_borrowed_temporary(expr)
-            || ty.map_or(true, |ty| {
-                // Avoid ICEs in needs_drop.
-                let ty = self.fcx.resolve_vars_if_possible(ty);
-                let ty = self.fcx.tcx.erase_regions(ty);
-                if ty.has_infer() {
-                    self.fcx
-                        .tcx
-                        .sess
-                        .delay_span_bug(expr.span, format!("inference variables in {ty}"));
-                    true
-                } else {
-                    ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
-                }
-            }) {
-            self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
-        } else {
-            let parent_expr = self
-                .fcx
-                .tcx
-                .hir()
-                .parent_iter(expr.hir_id)
-                .find(|(_, node)| matches!(node, hir::Node::Expr(_)))
-                .map(|(id, _)| id);
-            debug!("parent_expr: {:?}", parent_expr);
-            match parent_expr {
-                Some(parent) => Some(Scope { id: parent.local_id, data: ScopeData::Node }),
-                None => {
-                    self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
-                }
-            }
-        };
-
-        // If there are adjustments, then record the final type --
-        // this is the actual value that is being produced.
-        if let Some(adjusted_ty) = ty {
-            self.record(adjusted_ty, expr.hir_id, scope, Some(expr), expr.span);
-        }
-
-        // Also record the unadjusted type (which is the only type if
-        // there are no adjustments). The reason for this is that the
-        // unadjusted value is sometimes a "temporary" that would wind
-        // up in a MIR temporary.
-        //
-        // As an example, consider an expression like `vec![].push(x)`.
-        // Here, the `vec![]` would wind up MIR stored into a
-        // temporary variable `t` which we can borrow to invoke
-        // `<Vec<_>>::push(&mut t, x)`.
-        //
-        // Note that an expression can have many adjustments, and we
-        // are just ignoring those intermediate types. This is because
-        // those intermediate values are always linearly "consumed" by
-        // the other adjustments, and hence would never be directly
-        // captured in the MIR.
-        //
-        // (Note that this partly relies on the fact that the `Deref`
-        // traits always return references, which means their content
-        // can be reborrowed without needing to spill to a temporary.
-        // If this were not the case, then we could conceivably have
-        // to create intermediate temporaries.)
-        //
-        // The type table might not have information for this expression
-        // if it is in a malformed scope. (#66387)
-        if let Some(ty) = self.fcx.typeck_results.borrow().expr_ty_opt(expr) {
-            self.record(ty, expr.hir_id, scope, Some(expr), expr.span);
-        } else {
-            self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node");
-        }
-    }
-}
-
-#[derive(Default)]
-struct SuspendCheckData<'a, 'tcx> {
-    expr: Option<&'tcx Expr<'tcx>>,
-    source_span: Span,
-    yield_span: Span,
-    descr_pre: &'a str,
-    descr_post: &'a str,
-    plural_len: usize,
-}
-
-// Returns whether it emitted a diagnostic or not
-// Note that this fn and the proceeding one are based on the code
-// for creating must_use diagnostics
-//
-// Note that this technique was chosen over things like a `Suspend` marker trait
-// as it is simpler and has precedent in the compiler
-fn check_must_not_suspend_ty<'tcx>(
-    fcx: &FnCtxt<'_, 'tcx>,
-    ty: Ty<'tcx>,
-    hir_id: HirId,
-    data: SuspendCheckData<'_, 'tcx>,
-) -> bool {
-    if ty.is_unit()
-    // FIXME: should this check `Ty::is_inhabited_from`. This query is not available in this stage
-    // of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in
-    // `must_use`
-    // || !ty.is_inhabited_from(fcx.tcx, fcx.tcx.parent_module(hir_id).to_def_id(), fcx.param_env)
-    {
-        return false;
-    }
-
-    let plural_suffix = pluralize!(data.plural_len);
-
-    debug!("Checking must_not_suspend for {}", ty);
-
-    match *ty.kind() {
-        ty::Adt(..) if ty.is_box() => {
-            let boxed_ty = ty.boxed_ty();
-            let descr_pre = &format!("{}boxed ", data.descr_pre);
-            check_must_not_suspend_ty(fcx, boxed_ty, hir_id, SuspendCheckData { descr_pre, ..data })
-        }
-        ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did(), hir_id, data),
-        // FIXME: support adding the attribute to TAITs
-        ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
-            let mut has_emitted = false;
-            for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() {
-                // We only look at the `DefId`, so it is safe to skip the binder here.
-                if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
-                    predicate.kind().skip_binder()
-                {
-                    let def_id = poly_trait_predicate.trait_ref.def_id;
-                    let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix);
-                    if check_must_not_suspend_def(
-                        fcx.tcx,
-                        def_id,
-                        hir_id,
-                        SuspendCheckData { descr_pre, ..data },
-                    ) {
-                        has_emitted = true;
-                        break;
-                    }
-                }
-            }
-            has_emitted
-        }
-        ty::Dynamic(binder, _, _) => {
-            let mut has_emitted = false;
-            for predicate in binder.iter() {
-                if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
-                    let def_id = trait_ref.def_id;
-                    let descr_post = &format!(" trait object{}{}", plural_suffix, data.descr_post);
-                    if check_must_not_suspend_def(
-                        fcx.tcx,
-                        def_id,
-                        hir_id,
-                        SuspendCheckData { descr_post, ..data },
-                    ) {
-                        has_emitted = true;
-                        break;
-                    }
-                }
-            }
-            has_emitted
-        }
-        ty::Tuple(fields) => {
-            let mut has_emitted = false;
-            let comps = match data.expr.map(|e| &e.kind) {
-                Some(hir::ExprKind::Tup(comps)) if comps.len() == fields.len() => Some(comps),
-                _ => None,
-            };
-            for (i, ty) in fields.iter().enumerate() {
-                let descr_post = &format!(" in tuple element {i}");
-                let span = comps.and_then(|c| c.get(i)).map(|e| e.span).unwrap_or(data.source_span);
-                if check_must_not_suspend_ty(
-                    fcx,
-                    ty,
-                    hir_id,
-                    SuspendCheckData {
-                        descr_post,
-                        expr: comps.and_then(|comps| comps.get(i)),
-                        source_span: span,
-                        ..data
-                    },
-                ) {
-                    has_emitted = true;
-                }
-            }
-            has_emitted
-        }
-        ty::Array(ty, len) => {
-            let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix);
-            let target_usize =
-                len.try_eval_target_usize(fcx.tcx, fcx.param_env).unwrap_or(0) as usize;
-            let plural_len = target_usize.saturating_add(1);
-            check_must_not_suspend_ty(
-                fcx,
-                ty,
-                hir_id,
-                SuspendCheckData { descr_pre, plural_len, ..data },
-            )
-        }
-        // If drop tracking is enabled, we want to look through references, since the referent
-        // may not be considered live across the await point.
-        ty::Ref(_region, ty, _mutability) if fcx.sess().opts.unstable_opts.drop_tracking => {
-            let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
-            check_must_not_suspend_ty(fcx, ty, hir_id, SuspendCheckData { descr_pre, ..data })
-        }
-        _ => false,
-    }
-}
-
-fn check_must_not_suspend_def(
-    tcx: TyCtxt<'_>,
-    def_id: DefId,
-    hir_id: HirId,
-    data: SuspendCheckData<'_, '_>,
-) -> bool {
-    if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) {
-        tcx.struct_span_lint_hir(
-            rustc_session::lint::builtin::MUST_NOT_SUSPEND,
-            hir_id,
-            data.source_span,
-            DelayDm(|| {
-                format!(
-                    "{}`{}`{} held across a suspend point, but should not be",
-                    data.descr_pre,
-                    tcx.def_path_str(def_id),
-                    data.descr_post,
-                )
-            }),
-            |lint| {
-                // add span pointing to the offending yield/await
-                lint.span_label(data.yield_span, "the value is held across this suspend point");
-
-                // Add optional reason note
-                if let Some(note) = attr.value_str() {
-                    // FIXME(guswynn): consider formatting this better
-                    lint.span_note(data.source_span, note.to_string());
-                }
-
-                // Add some quick suggestions on what to do
-                // FIXME: can `drop` work as a suggestion here as well?
-                lint.span_help(
-                    data.source_span,
-                    "consider using a block (`{ ... }`) \
-                    to shrink the value's scope, ending before the suspend point",
-                );
-
-                lint
-            },
-        );
-
-        true
-    } else {
-        false
-    }
-}
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index f17f1d14bf3..6873382c4ac 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -32,7 +32,6 @@ pub mod expr_use_visitor;
 mod fallback;
 mod fn_ctxt;
 mod gather_locals;
-mod generator_interior;
 mod inherited;
 mod intrinsicck;
 mod mem_categorization;
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 2fe41c1197f..9c16b486dbc 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.visit_coercion_casts();
         wbcx.visit_user_provided_tys();
         wbcx.visit_user_provided_sigs();
-        wbcx.visit_generator_interior_types();
+        wbcx.visit_generator_interior();
         wbcx.visit_offset_of_container_types();
 
         wbcx.typeck_results.rvalue_scopes =
@@ -538,11 +538,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         );
     }
 
-    fn visit_generator_interior_types(&mut self) {
+    fn visit_generator_interior(&mut self) {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
-        self.typeck_results.generator_interior_types =
-            fcx_typeck_results.generator_interior_types.clone();
         self.tcx().with_stable_hashing_context(move |ref hcx| {
             for (&expr_def_id, predicates) in
                 fcx_typeck_results.generator_interior_predicates.to_sorted(hcx, false).into_iter()
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index ce097922aef..0e8f93cef17 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -798,14 +798,12 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
         }
     });
 
-    if tcx.sess.opts.unstable_opts.drop_tracking_mir {
-        tcx.hir().par_body_owners(|def_id| {
-            if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) {
-                tcx.ensure().mir_generator_witnesses(def_id);
-                tcx.ensure().check_generator_obligations(def_id);
-            }
-        });
-    }
+    tcx.hir().par_body_owners(|def_id| {
+        if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) {
+            tcx.ensure().mir_generator_witnesses(def_id);
+            tcx.ensure().check_generator_obligations(def_id);
+        }
+    });
 
     sess.time("layout_testing", || layout_test::test_layout(tcx));
     sess.time("abi_testing", || abi_test::test_abi(tcx));
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 1746cc8b719..2510ce71460 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -684,7 +684,6 @@ fn test_unstable_options_tracking_hash() {
     untracked!(dep_tasks, true);
     untracked!(dont_buffer_diagnostics, true);
     untracked!(dump_dep_graph, true);
-    untracked!(dump_drop_tracking_cfg, Some("cfg.dot".to_string()));
     untracked!(dump_mir, Some(String::from("abc")));
     untracked!(dump_mir_dataflow, true);
     untracked!(dump_mir_dir, String::from("abc"));
@@ -773,7 +772,6 @@ fn test_unstable_options_tracking_hash() {
     tracked!(debug_info_for_profiling, true);
     tracked!(debug_macros, true);
     tracked!(dep_info_omit_d_target, true);
-    tracked!(drop_tracking, true);
     tracked!(dual_proc_macros, true);
     tracked!(dwarf_version, Some(5));
     tracked!(emit_thin_lto, false);
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 1951db49e91..21575bf6b04 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -306,6 +306,7 @@ declare_lint! {
     /// pub async fn uhoh() {
     ///     let guard = SyncThing {};
     ///     yield_now().await;
+    ///     let _guard = guard;
     /// }
     /// ```
     ///
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 8ea9c60e4f2..b189e79df56 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -24,7 +24,6 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::GeneratorDiagnosticData;
 use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
 use rustc_serialize::opaque::MemDecoder;
 use rustc_serialize::{Decodable, Decoder};
@@ -1750,24 +1749,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .clone()
     }
 
-    fn get_generator_diagnostic_data(
-        self,
-        tcx: TyCtxt<'tcx>,
-        id: DefIndex,
-    ) -> Option<GeneratorDiagnosticData<'tcx>> {
-        self.root
-            .tables
-            .generator_diagnostic_data
-            .get(self, id)
-            .map(|param| param.decode((self, tcx)))
-            .map(|generator_data| GeneratorDiagnosticData {
-                generator_interior_types: generator_data.generator_interior_types,
-                hir_owner: generator_data.hir_owner,
-                nodes_types: generator_data.nodes_types,
-                adjustments: generator_data.adjustments,
-            })
-    }
-
     fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
         self.root.tables.attr_flags.get(self, index)
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index b682a153c77..b56fe375849 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -374,7 +374,6 @@ provide! { tcx, def_id, other, cdata,
 
     crate_extern_paths => { cdata.source().paths().cloned().collect() }
     expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
-    generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) }
     is_doc_hidden => { cdata.get_attr_flags(def_id.index).contains(AttrFlags::IS_DOC_HIDDEN) }
     doc_link_resolutions => { tcx.arena.alloc(cdata.get_doc_link_resolutions(def_id.index)) }
     doc_link_traits_in_scope => {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index cc7ae932e11..7506fc1bb05 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1439,7 +1439,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 }
             }
             if let DefKind::Generator = def_kind {
-                self.encode_info_for_generator(local_id);
+                let data = self.tcx.generator_kind(def_id).unwrap();
+                record!(self.tables.generator_kind[def_id] <- data);
             }
             if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
                 self.encode_info_for_adt(local_id);
@@ -1612,8 +1613,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()]
                     <- tcx.closure_saved_names_of_captured_variables(def_id));
 
-                if tcx.sess.opts.unstable_opts.drop_tracking_mir
-                    && let DefKind::Generator = self.tcx.def_kind(def_id)
+                if let DefKind::Generator = self.tcx.def_kind(def_id)
                     && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
                 {
                     record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
@@ -1640,6 +1640,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
             record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id));
 
+            if let DefKind::Generator = self.tcx.def_kind(def_id)
+                && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
+            {
+                record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
+            }
+
             let instance = ty::InstanceDef::Item(def_id.to_def_id());
             let unused = tcx.unused_generic_params(instance);
             self.tables.unused_generic_params.set(def_id.local_def_index, unused);
@@ -1712,15 +1718,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body);
     }
 
-    #[instrument(level = "debug", skip(self))]
-    fn encode_info_for_generator(&mut self, def_id: LocalDefId) {
-        let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
-        let data = self.tcx.generator_kind(def_id).unwrap();
-        let generator_diagnostic_data = typeck_result.get_generator_diagnostic_data();
-        record!(self.tables.generator_kind[def_id.to_def_id()] <- data);
-        record!(self.tables.generator_diagnostic_data[def_id.to_def_id()]  <- generator_diagnostic_data);
-    }
-
     fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
         empty_proc_macro!(self);
         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 43d5cf43a81..09b2a1a0cb2 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -23,7 +23,7 @@ use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::mir;
 use rustc_middle::ty::fast_reject::SimplifiedType;
 use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams};
-use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
+use rustc_middle::ty::{DeducedParamAttrs, ParameterizedOverTcx, TyCtxt};
 use rustc_middle::util::Providers;
 use rustc_serialize::opaque::FileEncoder;
 use rustc_session::config::SymbolManglingVersion;
@@ -452,7 +452,6 @@ define_tables! {
     // definitions from any given crate.
     def_keys: Table<DefIndex, LazyValue<DefKey>>,
     proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
-    generator_diagnostic_data: Table<DefIndex, LazyValue<GeneratorDiagnosticData<'static>>>,
     variant_data: Table<DefIndex, LazyValue<VariantData>>,
     assoc_container: Table<DefIndex, ty::AssocItemContainer>,
     macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6928f59c3fd..5986a8b1cd8 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -44,7 +44,6 @@ use crate::traits::{
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::layout::ValidityRequirement;
 use crate::ty::util::AlwaysRequiresDrop;
-use crate::ty::GeneratorDiagnosticData;
 use crate::ty::TyCtxtFeed;
 use crate::ty::{
     self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt,
@@ -2149,12 +2148,6 @@ rustc_queries! {
         desc { "computing the backend features for CLI flags" }
     }
 
-    query generator_diagnostic_data(key: DefId) -> &'tcx Option<GeneratorDiagnosticData<'tcx>> {
-        arena_cache
-        desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) }
-        separate_provide_extern
-    }
-
     query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> {
         desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
     }
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 7c05deae90a..dff7ff8c66b 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -566,6 +566,5 @@ impl_binder_encode_decode! {
     ty::TraitPredicate<'tcx>,
     ty::ExistentialPredicate<'tcx>,
     ty::TraitRef<'tcx>,
-    Vec<ty::GeneratorInteriorTypeCause<'tcx>>,
     ty::ExistentialTraitRef<'tcx>,
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b050208b4a6..aa1e7f216a0 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -106,9 +106,8 @@ pub use self::sty::{
 };
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
-    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
-    UserTypeAnnotationIndex,
+    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, TypeckResults,
+    UserType, UserTypeAnnotationIndex,
 };
 
 pub mod _match;
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index f1093e88312..9aa673e4418 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -132,5 +132,4 @@ parameterized_over_tcx! {
     ty::Predicate,
     ty::Clause,
     ty::ClauseKind,
-    ty::GeneratorDiagnosticData,
 }
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 69c4c588c44..a44224e4dc7 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -189,10 +189,6 @@ pub struct TypeckResults<'tcx> {
     /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
     pub rvalue_scopes: RvalueScopes,
 
-    /// Stores the type, expression, span and optional scope span of all types
-    /// that are live across the yield of this generator (if a generator).
-    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-
     /// Stores the predicates that apply on generator witness types.
     /// formatting modified file tests/ui/generator/retain-resume-ref.rs
     pub generator_interior_predicates:
@@ -212,49 +208,6 @@ pub struct TypeckResults<'tcx> {
     offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
 }
 
-/// Whenever a value may be live across a generator yield, the type of that value winds up in the
-/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
-/// captured types that can be useful for diagnostics. In particular, it stores the span that
-/// caused a given type to be recorded, along with the scope that enclosed the value (which can
-/// be used to find the await that the value is live across).
-///
-/// For example:
-///
-/// ```ignore (pseudo-Rust)
-/// async move {
-///     let x: T = expr;
-///     foo.await
-///     ...
-/// }
-/// ```
-///
-/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
-/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
-#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct GeneratorInteriorTypeCause<'tcx> {
-    /// Type of the captured binding.
-    pub ty: Ty<'tcx>,
-    /// Span of the binding that was captured.
-    pub span: Span,
-    /// Span of the scope of the captured binding.
-    pub scope_span: Option<Span>,
-    /// Span of `.await` or `yield` expression.
-    pub yield_span: Span,
-    /// Expr which the type evaluated from.
-    pub expr: Option<hir::HirId>,
-}
-
-// This type holds diagnostic information on generators and async functions across crate boundaries
-// and is used to provide better error messages
-#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
-pub struct GeneratorDiagnosticData<'tcx> {
-    pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-    pub hir_owner: DefId,
-    pub nodes_types: ItemLocalMap<Ty<'tcx>>,
-    pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-}
-
 impl<'tcx> TypeckResults<'tcx> {
     pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
         TypeckResults {
@@ -278,7 +231,6 @@ impl<'tcx> TypeckResults<'tcx> {
             closure_min_captures: Default::default(),
             closure_fake_reads: Default::default(),
             rvalue_scopes: Default::default(),
-            generator_interior_types: ty::Binder::dummy(Default::default()),
             generator_interior_predicates: Default::default(),
             treat_byte_string_as_slice: Default::default(),
             closure_size_eval: Default::default(),
@@ -351,28 +303,6 @@ impl<'tcx> TypeckResults<'tcx> {
         LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
     }
 
-    pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
-        let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
-            vec.iter()
-                .map(|item| {
-                    GeneratorInteriorTypeCause {
-                        ty: item.ty,
-                        span: item.span,
-                        scope_span: item.scope_span,
-                        yield_span: item.yield_span,
-                        expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
-                    }
-                })
-                .collect::<Vec<_>>()
-        });
-        GeneratorDiagnosticData {
-            generator_interior_types: generator_interior_type,
-            hir_owner: self.hir_owner.to_def_id(),
-            nodes_types: self.node_types.clone(),
-            adjustments: self.adjustments.clone(),
-        }
-    }
-
     pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
         self.node_type_opt(id).unwrap_or_else(|| {
             bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 9bcdc7d728d..8a807d786a5 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -853,60 +853,7 @@ impl StorageConflictVisitor<'_, '_, '_> {
     }
 }
 
-/// Validates the typeck view of the generator against the actual set of types saved between
-/// yield points.
-fn sanitize_witness<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    witness: Ty<'tcx>,
-    upvars: &'tcx ty::List<Ty<'tcx>>,
-    layout: &GeneratorLayout<'tcx>,
-) {
-    let did = body.source.def_id();
-    let param_env = tcx.param_env(did);
-
-    let allowed_upvars = tcx.normalize_erasing_regions(param_env, upvars);
-    let allowed = match witness.kind() {
-        &ty::GeneratorWitness(interior_tys) => {
-            tcx.normalize_erasing_late_bound_regions(param_env, interior_tys)
-        }
-        _ => {
-            tcx.sess.delay_span_bug(
-                body.span,
-                format!("unexpected generator witness type {:?}", witness.kind()),
-            );
-            return;
-        }
-    };
-
-    let mut mismatches = Vec::new();
-    for fty in &layout.field_tys {
-        if fty.ignore_for_traits {
-            continue;
-        }
-        let decl_ty = tcx.normalize_erasing_regions(param_env, fty.ty);
-
-        // Sanity check that typeck knows about the type of locals which are
-        // live across a suspension point
-        if !allowed.contains(&decl_ty) && !allowed_upvars.contains(&decl_ty) {
-            mismatches.push(decl_ty);
-        }
-    }
-
-    if !mismatches.is_empty() {
-        span_bug!(
-            body.span,
-            "Broken MIR: generator contains type {:?} in MIR, \
-                       but typeck only knows about {} and {:?}",
-            mismatches,
-            allowed,
-            allowed_upvars
-        );
-    }
-}
-
 fn compute_layout<'tcx>(
-    tcx: TyCtxt<'tcx>,
     liveness: LivenessInfo,
     body: &Body<'tcx>,
 ) -> (
@@ -932,27 +879,20 @@ fn compute_layout<'tcx>(
         let decl = &body.local_decls[local];
         debug!(?decl);
 
-        let ignore_for_traits = if tcx.sess.opts.unstable_opts.drop_tracking_mir {
-            // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
-            // the information. This is alright, since `ignore_for_traits` is only relevant when
-            // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
-            // default.
-            match decl.local_info {
-                // Do not include raw pointers created from accessing `static` items, as those could
-                // well be re-created by another access to the same static.
-                ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
-                    !is_thread_local
-                }
-                // Fake borrows are only read by fake reads, so do not have any reality in
-                // post-analysis MIR.
-                ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
-                _ => false,
+        // Do not `assert_crate_local` here, as post-borrowck cleanup may have already cleared
+        // the information. This is alright, since `ignore_for_traits` is only relevant when
+        // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer
+        // default.
+        let ignore_for_traits = match decl.local_info {
+            // Do not include raw pointers created from accessing `static` items, as those could
+            // well be re-created by another access to the same static.
+            ClearCrossCrate::Set(box LocalInfo::StaticRef { is_thread_local, .. }) => {
+                !is_thread_local
             }
-        } else {
-            // FIXME(#105084) HIR-based drop tracking does not account for all the temporaries that
-            // MIR building may introduce. This leads to wrongly ignored types, but this is
-            // necessary for internal consistency and to avoid ICEs.
-            decl.internal
+            // Fake borrows are only read by fake reads, so do not have any reality in
+            // post-analysis MIR.
+            ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
+            _ => false,
         };
         let decl =
             GeneratorSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits };
@@ -1445,8 +1385,6 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
 ) -> Option<GeneratorLayout<'tcx>> {
-    assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
-
     let (body, _) = tcx.mir_promoted(def_id);
     let body = body.borrow();
     let body = &*body;
@@ -1469,7 +1407,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
     // Extract locals which are live across suspension point into `layout`
     // `remap` gives a mapping from local indices onto generator struct indices
     // `storage_liveness` tells us which locals have live storage at suspension points
-    let (_, generator_layout, _) = compute_layout(tcx, liveness_info, body);
+    let (_, generator_layout, _) = compute_layout(liveness_info, body);
 
     check_suspend_tys(tcx, &generator_layout, &body);
 
@@ -1489,15 +1427,10 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         let gen_ty = body.local_decls.raw[1].ty;
 
         // Get the discriminant type and args which typeck computed
-        let (discr_ty, upvars, interior, movable) = match *gen_ty.kind() {
+        let (discr_ty, movable) = match *gen_ty.kind() {
             ty::Generator(_, args, movability) => {
                 let args = args.as_generator();
-                (
-                    args.discr_ty(tcx),
-                    args.upvar_tys(),
-                    args.witness(),
-                    movability == hir::Movability::Movable,
-                )
+                (args.discr_ty(tcx), movability == hir::Movability::Movable)
             }
             _ => {
                 tcx.sess.delay_span_bug(body.span, format!("unexpected generator type {gen_ty}"));
@@ -1574,13 +1507,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
         // Extract locals which are live across suspension point into `layout`
         // `remap` gives a mapping from local indices onto generator struct indices
         // `storage_liveness` tells us which locals have live storage at suspension points
-        let (remap, layout, storage_liveness) = compute_layout(tcx, liveness_info, body);
-
-        if tcx.sess.opts.unstable_opts.validate_mir
-            && !tcx.sess.opts.unstable_opts.drop_tracking_mir
-        {
-            sanitize_witness(tcx, body, interior, upvars, &layout);
-        }
+        let (remap, layout, storage_liveness) = compute_layout(liveness_info, body);
 
         let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id()));
 
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index d55b0cbe635..d7fef093278 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -358,9 +358,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
 /// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
 /// end up missing the source MIR due to stealing happening.
 fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
-    if tcx.sess.opts.unstable_opts.drop_tracking_mir
-        && let DefKind::Generator = tcx.def_kind(def)
-    {
+    if let DefKind::Generator = tcx.def_kind(def) {
         tcx.ensure_with_value().mir_generator_witnesses(def);
     }
     let mir_borrowck = tcx.mir_borrowck(def);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 23f2be632b2..c1424db600e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1458,17 +1458,11 @@ options! {
     dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED],
         "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) \
         (default: no)"),
-    drop_tracking: bool = (false, parse_bool, [TRACKED],
-        "enables drop tracking in generators (default: no)"),
-    drop_tracking_mir: bool = (false, parse_bool, [TRACKED],
-        "enables drop tracking on MIR in generators (default: no)"),
     dual_proc_macros: bool = (false, parse_bool, [TRACKED],
         "load proc macros for both target and host, but only link to the target (default: no)"),
     dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
         "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) \
         (default: no)"),
-    dump_drop_tracking_cfg: Option<String> = (None, parse_opt_string, [UNTRACKED],
-        "dump drop-tracking control-flow graph as a `.dot` file (default: no)"),
     dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
         "dump MIR state to file.
         `val` is used to select which passes and functions to dump. For example:
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index d1f2c1b27fd..3d9b8539ee2 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -779,6 +779,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         | ty::Str
         | ty::Never
         | ty::Foreign(..)
+        | ty::GeneratorWitnessMIR(..)
         | ty::GeneratorWitness(..) => {}
 
         ty::Bool => {
@@ -973,12 +974,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
             );
         }
 
-        ty::Bound(..)
-        | ty::Error(..)
-        | ty::GeneratorWitnessMIR(..)
-        | ty::Infer(..)
-        | ty::Param(..)
-        | ty::Placeholder(..) => {
+        ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => {
             bug!("transform_ty: unexpected `{:?}`", ty.kind());
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index bb96e135741..428267a923e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -30,10 +30,9 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTi
 use rustc_middle::hir::map;
 use rustc_middle::ty::error::TypeError::{self, Sorts};
 use rustc_middle::ty::{
-    self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, GenericArgs, InferTy, IsSuggestable,
-    ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
-    TypeVisitableExt, TypeckResults,
+    self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
+    InferTy, IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeVisitableExt, TypeckResults,
 };
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -58,15 +57,12 @@ pub enum GeneratorInteriorOrUpvar {
 // This type provides a uniform interface to retrieve data on generators, whether it originated from
 // the local crate being compiled or from a foreign crate.
 #[derive(Debug)]
-pub enum GeneratorData<'tcx, 'a> {
-    Local(&'a TypeckResults<'tcx>),
-    Foreign(&'tcx GeneratorDiagnosticData<'tcx>),
-}
+struct GeneratorData<'tcx, 'a>(&'a TypeckResults<'tcx>);
 
 impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
-    // Try to get information about variables captured by the generator that matches a type we are
-    // looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
-    // meet an obligation
+    /// Try to get information about variables captured by the generator that matches a type we are
+    /// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
+    /// meet an obligation
     fn try_get_upvar_span<F>(
         &self,
         infer_context: &InferCtxt<'tcx>,
@@ -76,27 +72,21 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
     where
         F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
     {
-        match self {
-            GeneratorData::Local(typeck_results) => {
-                infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
-                    upvars.iter().find_map(|(upvar_id, upvar)| {
-                        let upvar_ty = typeck_results.node_type(*upvar_id);
-                        let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
-                        ty_matches(ty::Binder::dummy(upvar_ty))
-                            .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
-                    })
-                })
-            }
-            GeneratorData::Foreign(_) => None,
-        }
+        infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
+            upvars.iter().find_map(|(upvar_id, upvar)| {
+                let upvar_ty = self.0.node_type(*upvar_id);
+                let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
+                ty_matches(ty::Binder::dummy(upvar_ty))
+                    .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
+            })
+        })
     }
 
-    // Try to get the span of a type being awaited on that matches the type we are looking with the
-    // `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
-    // obligation
+    /// Try to get the span of a type being awaited on that matches the type we are looking with the
+    /// `ty_matches` function. We uses it to find awaited type which causes a failure to meet an
+    /// obligation
     fn get_from_await_ty<F>(
         &self,
-        tcx: TyCtxt<'tcx>,
         visitor: AwaitsVisitor,
         hir: map::Map<'tcx>,
         ty_matches: F,
@@ -104,69 +94,12 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
     where
         F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
     {
-        match self {
-            GeneratorData::Local(typeck_results) => visitor
-                .awaits
-                .into_iter()
-                .map(|id| hir.expect_expr(id))
-                .find(|await_expr| {
-                    ty_matches(ty::Binder::dummy(typeck_results.expr_ty_adjusted(&await_expr)))
-                })
-                .map(|expr| expr.span),
-            GeneratorData::Foreign(generator_diagnostic_data) => visitor
-                .awaits
-                .into_iter()
-                .map(|id| hir.expect_expr(id))
-                .find(|await_expr| {
-                    ty_matches(ty::Binder::dummy(
-                        generator_diagnostic_data
-                            .adjustments
-                            .get(&await_expr.hir_id.local_id)
-                            .map_or::<&[ty::adjustment::Adjustment<'tcx>], _>(&[], |a| &a[..])
-                            .last()
-                            .map_or_else::<Ty<'tcx>, _, _>(
-                                || {
-                                    generator_diagnostic_data
-                                        .nodes_types
-                                        .get(&await_expr.hir_id.local_id)
-                                        .cloned()
-                                        .unwrap_or_else(|| {
-                                            bug!(
-                                                "node_type: no type for node {}",
-                                                tcx.hir().node_to_string(await_expr.hir_id)
-                                            )
-                                        })
-                                },
-                                |adj| adj.target,
-                            ),
-                    ))
-                })
-                .map(|expr| expr.span),
-        }
-    }
-
-    /// Get the type, expression, span and optional scope span of all types
-    /// that are live across the yield of this generator
-    fn get_generator_interior_types(
-        &self,
-    ) -> ty::Binder<'tcx, &[GeneratorInteriorTypeCause<'tcx>]> {
-        match self {
-            GeneratorData::Local(typeck_result) => {
-                typeck_result.generator_interior_types.as_deref()
-            }
-            GeneratorData::Foreign(generator_diagnostic_data) => {
-                generator_diagnostic_data.generator_interior_types.as_deref()
-            }
-        }
-    }
-
-    // Used to get the source of the data, note we don't have as much information for generators
-    // originated from foreign crates
-    fn is_foreign(&self) -> bool {
-        match self {
-            GeneratorData::Local(_) => false,
-            GeneratorData::Foreign(_) => true,
-        }
+        visitor
+            .awaits
+            .into_iter()
+            .map(|id| hir.expect_expr(id))
+            .find(|await_expr| ty_matches(ty::Binder::dummy(self.0.expr_ty_adjusted(&await_expr))))
+            .map(|expr| expr.span)
     }
 }
 
@@ -316,7 +249,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         outer_generator: Option<DefId>,
         trait_pred: ty::TraitPredicate<'tcx>,
         target_ty: Ty<'tcx>,
-        typeck_results: Option<&ty::TypeckResults<'tcx>>,
+        typeck_results: &ty::TypeckResults<'tcx>,
         obligation: &PredicateObligation<'tcx>,
         next_code: Option<&ObligationCauseCode<'tcx>>,
     );
@@ -2351,12 +2284,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         // cycles. If we can't use resolved types because the generator comes from another crate,
         // we still provide a targeted error but without all the relevant spans.
         let generator_data = match &self.typeck_results {
-            Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData::Local(&t),
+            Some(t) if t.hir_owner.to_def_id() == generator_did_root => GeneratorData(&t),
             _ if generator_did.is_local() => {
-                GeneratorData::Local(self.tcx.typeck(generator_did.expect_local()))
-            }
-            _ if let Some(generator_diag_data) = self.tcx.generator_diagnostic_data(generator_did) => {
-                GeneratorData::Foreign(generator_diag_data)
+                GeneratorData(self.tcx.typeck(generator_did.expect_local()))
             }
             _ => return false,
         };
@@ -2368,30 +2298,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         let mut interior_or_upvar_span = None;
 
-        let from_awaited_ty = generator_data.get_from_await_ty(self.tcx, visitor, hir, ty_matches);
+        let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
         debug!(?from_awaited_ty);
 
-        // The generator interior types share the same binders
-        if let Some(cause) =
-            generator_data.get_generator_interior_types().skip_binder().iter().find(
-                |ty::GeneratorInteriorTypeCause { ty, .. }| {
-                    ty_matches(generator_data.get_generator_interior_types().rebind(*ty))
-                },
-            )
-        {
-            let ty::GeneratorInteriorTypeCause { span, scope_span, yield_span, expr, .. } = cause;
-
-            interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(
-                *span,
-                Some((*scope_span, *yield_span, *expr, from_awaited_ty)),
-            ));
-
-            if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
-                interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span, None));
-            }
-        } else if self.tcx.sess.opts.unstable_opts.drop_tracking_mir
-            // Avoid disclosing internal information to downstream crates.
-            && generator_did.is_local()
+        // Avoid disclosing internal information to downstream crates.
+        if generator_did.is_local()
             // Try to avoid cycles.
             && !generator_within_in_progress_typeck
             && let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did)
@@ -2420,17 +2331,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
         }
 
-        if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
+        if interior_or_upvar_span.is_none() && !generator_did.is_local() {
             interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(span, None));
         }
 
         debug!(?interior_or_upvar_span);
         if let Some(interior_or_upvar_span) = interior_or_upvar_span {
             let is_async = self.tcx.generator_is_async(generator_did);
-            let typeck_results = match generator_data {
-                GeneratorData::Local(typeck_results) => Some(typeck_results),
-                GeneratorData::Foreign(_) => None,
-            };
+            let typeck_results = generator_data.0;
             self.note_obligation_cause_for_async_await(
                 err,
                 interior_or_upvar_span,
@@ -2459,7 +2367,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         outer_generator: Option<DefId>,
         trait_pred: ty::TraitPredicate<'tcx>,
         target_ty: Ty<'tcx>,
-        typeck_results: Option<&ty::TypeckResults<'tcx>>,
+        typeck_results: &ty::TypeckResults<'tcx>,
         obligation: &PredicateObligation<'tcx>,
         next_code: Option<&ObligationCauseCode<'tcx>>,
     ) {
@@ -2584,11 +2492,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         );
                     } else {
                         // Look at the last interior type to get a span for the `.await`.
-                        debug!(
-                            generator_interior_types = ?format_args!(
-                                "{:#?}", typeck_results.as_ref().map(|t| &t.generator_interior_types)
-                            ),
-                        );
                         explain_yield(interior_span, yield_span, scope_span);
                     }
 
@@ -2608,14 +2511,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
                             // ```
                             //
-                            let is_region_borrow = if let Some(typeck_results) = typeck_results {
-                                typeck_results
-                                    .expr_adjustments(expr)
-                                    .iter()
-                                    .any(|adj| adj.is_region_borrow())
-                            } else {
-                                false
-                            };
+                            let is_region_borrow = typeck_results
+                                .expr_adjustments(expr)
+                                .iter()
+                                .any(|adj| adj.is_region_borrow());
 
                             // ```rust
                             // struct Foo(*const u8);
@@ -2628,16 +2527,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                     DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(),
                                     _ => false,
                                 };
-                            if let Some(typeck_results) = typeck_results {
-                                if (typeck_results.is_method_call(e) && is_region_borrow)
-                                    || is_raw_borrow_inside_fn_like_call
-                                {
-                                    err.span_help(
-                                        parent_span,
-                                        "consider moving this into a `let` \
+                            if (typeck_results.is_method_call(e) && is_region_borrow)
+                                || is_raw_borrow_inside_fn_like_call
+                            {
+                                err.span_help(
+                                    parent_span,
+                                    "consider moving this into a `let` \
                         binding to create a shorter lived borrow",
-                                    );
-                                }
+                                );
                             }
                         }
                     }
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 1fc5d9359a4..76d381dd19f 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
 use rustc_session::Limit;
-use rustc_span::{sym, DUMMY_SP};
+use rustc_span::sym;
 
 use crate::errors::NeedsDropOverflow;
 
@@ -133,7 +133,7 @@ where
                     // The information required to determine whether a generator has drop is
                     // computed on MIR, while this very method is used to build MIR.
                     // To avoid cycles, we consider that generators always require drop.
-                    ty::Generator(..) if tcx.sess.opts.unstable_opts.drop_tracking_mir => {
+                    ty::Generator(..) => {
                         return Some(Err(AlwaysRequiresDrop));
                     }
 
@@ -145,29 +145,6 @@ where
                         }
                     }
 
-                    ty::Generator(def_id, args, _) => {
-                        let args = args.as_generator();
-                        for upvar in args.upvar_tys() {
-                            queue_type(self, upvar);
-                        }
-
-                        let witness = args.witness();
-                        let interior_tys = match witness.kind() {
-                            &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys),
-                            _ => {
-                                tcx.sess.delay_span_bug(
-                                    tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP),
-                                    format!("unexpected generator witness type {witness:?}"),
-                                );
-                                return Some(Err(AlwaysRequiresDrop));
-                            }
-                        };
-
-                        for interior_ty in interior_tys {
-                            queue_type(self, interior_ty);
-                        }
-                    }
-
                     // Check for a `Drop` impl and whether this is a union or
                     // `ManuallyDrop`. If it's a struct or enum without a `Drop`
                     // impl then check whether the field types need `Drop`.
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index d40a385435a..7dd808a7b3b 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{match_def_path, paths};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
+use rustc_hir::{AsyncGeneratorKind, Body, GeneratorKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::GeneratorInteriorTypeCause;
+use rustc_middle::mir::GeneratorLayout;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
 
@@ -197,28 +197,35 @@ impl LateLintPass<'_> for AwaitHolding {
     fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
         use AsyncGeneratorKind::{Block, Closure, Fn};
         if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind {
-            let body_id = BodyId {
-                hir_id: body.value.hir_id,
-            };
-            let typeck_results = cx.tcx.typeck_body(body_id);
-            self.check_interior_types(
-                cx,
-                typeck_results.generator_interior_types.as_ref().skip_binder(),
-                body.value.span,
-            );
+            let def_id = cx.tcx.hir().body_owner_def_id(body.id());
+            if let Some(generator_layout) = cx.tcx.mir_generator_witnesses(def_id) {
+                self.check_interior_types(cx, generator_layout);
+            }
         }
     }
 }
 
 impl AwaitHolding {
-    fn check_interior_types(&self, cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) {
-        for ty_cause in ty_causes {
+    fn check_interior_types(&self, cx: &LateContext<'_>, generator: &GeneratorLayout<'_>) {
+        for (ty_index, ty_cause) in generator.field_tys.iter_enumerated() {
             if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
+                let await_points = || {
+                    generator
+                        .variant_source_info
+                        .iter_enumerated()
+                        .filter_map(|(variant, source_info)| {
+                            generator.variant_fields[variant]
+                                .raw
+                                .contains(&ty_index)
+                                .then_some(source_info.span)
+                        })
+                        .collect::<Vec<_>>()
+                };
                 if is_mutex_guard(cx, adt.did()) {
                     span_lint_and_then(
                         cx,
                         AWAIT_HOLDING_LOCK,
-                        ty_cause.span,
+                        ty_cause.source_info.span,
                         "this `MutexGuard` is held across an `await` point",
                         |diag| {
                             diag.help(
@@ -226,7 +233,7 @@ impl AwaitHolding {
                                 `MutexGuard` is dropped before calling await",
                             );
                             diag.span_note(
-                                ty_cause.scope_span.unwrap_or(span),
+                                await_points(),
                                 "these are all the `await` points this lock is held through",
                             );
                         },
@@ -235,18 +242,18 @@ impl AwaitHolding {
                     span_lint_and_then(
                         cx,
                         AWAIT_HOLDING_REFCELL_REF,
-                        ty_cause.span,
+                        ty_cause.source_info.span,
                         "this `RefCell` reference is held across an `await` point",
                         |diag| {
                             diag.help("ensure the reference is dropped before calling `await`");
                             diag.span_note(
-                                ty_cause.scope_span.unwrap_or(span),
+                                await_points(),
                                 "these are all the `await` points this reference is held through",
                             );
                         },
                     );
                 } else if let Some(disallowed) = self.def_ids.get(&adt.did()) {
-                    emit_invalid_type(cx, ty_cause.span, disallowed);
+                    emit_invalid_type(cx, ty_cause.source_info.span, disallowed);
                 }
             }
         }