about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs224
-rw-r--r--src/doc/rustc/src/platform-support/nuttx.md2
-rw-r--r--src/tools/rust-analyzer/.editorconfig2
-rw-r--r--src/tools/rust-analyzer/.github/workflows/ci.yaml6
-rw-r--r--src/tools/rust-analyzer/Cargo.lock86
-rw-r--r--src/tools/rust-analyzer/Cargo.toml14
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/visibility.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs52
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs1115
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs2229
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs2457
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs1268
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs126
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs55
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs35
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/annotations.rs238
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html12
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/benchmark.rs13
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast208
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs17
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs9
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs12
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram3
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs6
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ptr.rs2
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc44
-rw-r--r--src/tools/rust-analyzer/editors/code/package-lock.json1525
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json53
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts4
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts43
-rw-r--r--src/tools/rust-analyzer/editors/code/src/main.ts9
-rw-r--r--src/tools/rust-analyzer/lib/line-index/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/lib/line-index/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/lib/line-index/src/tests.rs23
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs2
65 files changed, 7209 insertions, 3031 deletions
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index 94088156756..9a533ea024d 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph::DirectedGraph;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::bug;
 use rustc_middle::mir::coverage::{CounterId, CovTerm, Expression, ExpressionId, Op};
 use tracing::{debug, debug_span, instrument};
 
@@ -58,13 +57,13 @@ pub(super) struct CoverageCounters {
     counter_increment_sites: IndexVec<CounterId, CounterIncrementSite>,
 
     /// Coverage counters/expressions that are associated with individual BCBs.
-    bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>,
+    node_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>,
     /// Coverage counters/expressions that are associated with the control-flow
     /// edge between two BCBs.
     ///
     /// We currently don't iterate over this map, but if we do in the future,
     /// switch it back to `FxIndexMap` to avoid query stability hazards.
-    bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>,
+    edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>,
 
     /// Table of expression data, associating each expression ID with its
     /// corresponding operator (+ or -) and its LHS/RHS operands.
@@ -78,20 +77,20 @@ impl CoverageCounters {
     /// Ensures that each BCB node needing a counter has one, by creating physical
     /// counters or counter expressions for nodes and edges as required.
     pub(super) fn make_bcb_counters(
-        basic_coverage_blocks: &CoverageGraph,
+        graph: &CoverageGraph,
         bcb_needs_counter: &BitSet<BasicCoverageBlock>,
     ) -> Self {
-        let mut counters = MakeBcbCounters::new(basic_coverage_blocks, bcb_needs_counter);
-        counters.make_bcb_counters();
+        let mut builder = CountersBuilder::new(graph, bcb_needs_counter);
+        builder.make_bcb_counters();
 
-        counters.coverage_counters
+        builder.counters
     }
 
     fn with_num_bcbs(num_bcbs: usize) -> Self {
         Self {
             counter_increment_sites: IndexVec::new(),
-            bcb_counters: IndexVec::from_elem_n(None, num_bcbs),
-            bcb_edge_counters: FxHashMap::default(),
+            node_counters: IndexVec::from_elem_n(None, num_bcbs),
+            edge_counters: FxHashMap::default(),
             expressions: IndexVec::new(),
             expressions_memo: FxHashMap::default(),
         }
@@ -104,24 +103,18 @@ impl CoverageCounters {
         BcbCounter::Counter { id }
     }
 
-    /// Creates a new physical counter attached a BCB node.
-    /// The node must not already have a counter.
+    /// Creates a new physical counter for a BCB node.
     fn make_phys_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
-        let counter = self.make_counter_inner(CounterIncrementSite::Node { bcb });
-        debug!(?bcb, ?counter, "node gets a physical counter");
-        self.set_bcb_counter(bcb, counter)
+        self.make_counter_inner(CounterIncrementSite::Node { bcb })
     }
 
-    /// Creates a new physical counter attached to a BCB edge.
-    /// The edge must not already have a counter.
+    /// Creates a new physical counter for a BCB edge.
     fn make_phys_edge_counter(
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
     ) -> BcbCounter {
-        let counter = self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb });
-        debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
-        self.set_bcb_edge_counter(from_bcb, to_bcb, counter)
+        self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb })
     }
 
     fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
@@ -193,35 +186,31 @@ impl CoverageCounters {
         self.counter_increment_sites.len()
     }
 
-    fn set_bcb_counter(&mut self, bcb: BasicCoverageBlock, counter_kind: BcbCounter) -> BcbCounter {
-        if let Some(replaced) = self.bcb_counters[bcb].replace(counter_kind) {
-            bug!(
-                "attempt to set a BasicCoverageBlock coverage counter more than once; \
-                {bcb:?} already had counter {replaced:?}",
-            );
-        } else {
-            counter_kind
-        }
+    fn set_node_counter(&mut self, bcb: BasicCoverageBlock, counter: BcbCounter) -> BcbCounter {
+        let existing = self.node_counters[bcb].replace(counter);
+        assert!(
+            existing.is_none(),
+            "node {bcb:?} already has a counter: {existing:?} => {counter:?}"
+        );
+        counter
     }
 
-    fn set_bcb_edge_counter(
+    fn set_edge_counter(
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
-        counter_kind: BcbCounter,
+        counter: BcbCounter,
     ) -> BcbCounter {
-        if let Some(replaced) = self.bcb_edge_counters.insert((from_bcb, to_bcb), counter_kind) {
-            bug!(
-                "attempt to set an edge counter more than once; from_bcb: \
-                {from_bcb:?} already had counter {replaced:?}",
-            );
-        } else {
-            counter_kind
-        }
+        let existing = self.edge_counters.insert((from_bcb, to_bcb), counter);
+        assert!(
+            existing.is_none(),
+            "edge ({from_bcb:?} -> {to_bcb:?}) already has a counter: {existing:?} => {counter:?}"
+        );
+        counter
     }
 
     pub(super) fn term_for_bcb(&self, bcb: BasicCoverageBlock) -> Option<CovTerm> {
-        self.bcb_counters[bcb].map(|counter| counter.as_term())
+        self.node_counters[bcb].map(|counter| counter.as_term())
     }
 
     /// Returns an iterator over all the nodes/edges in the coverage graph that
@@ -238,7 +227,7 @@ impl CoverageCounters {
     pub(super) fn bcb_nodes_with_coverage_expressions(
         &self,
     ) -> impl Iterator<Item = (BasicCoverageBlock, ExpressionId)> + Captures<'_> {
-        self.bcb_counters.iter_enumerated().filter_map(|(bcb, &counter_kind)| match counter_kind {
+        self.node_counters.iter_enumerated().filter_map(|(bcb, &counter)| match counter {
             // Yield the BCB along with its associated expression ID.
             Some(BcbCounter::Expression { id }) => Some((bcb, id)),
             // This BCB is associated with a counter or nothing, so skip it.
@@ -265,22 +254,20 @@ impl CoverageCounters {
     }
 }
 
-/// Helper struct that allows counter creation to inspect the BCB graph.
-struct MakeBcbCounters<'a> {
-    coverage_counters: CoverageCounters,
-    basic_coverage_blocks: &'a CoverageGraph,
+/// Helper struct that allows counter creation to inspect the BCB graph, and
+/// the set of nodes that need counters.
+struct CountersBuilder<'a> {
+    counters: CoverageCounters,
+    graph: &'a CoverageGraph,
     bcb_needs_counter: &'a BitSet<BasicCoverageBlock>,
 }
 
-impl<'a> MakeBcbCounters<'a> {
-    fn new(
-        basic_coverage_blocks: &'a CoverageGraph,
-        bcb_needs_counter: &'a BitSet<BasicCoverageBlock>,
-    ) -> Self {
-        assert_eq!(basic_coverage_blocks.num_nodes(), bcb_needs_counter.domain_size());
+impl<'a> CountersBuilder<'a> {
+    fn new(graph: &'a CoverageGraph, bcb_needs_counter: &'a BitSet<BasicCoverageBlock>) -> Self {
+        assert_eq!(graph.num_nodes(), bcb_needs_counter.domain_size());
         Self {
-            coverage_counters: CoverageCounters::with_num_bcbs(basic_coverage_blocks.num_nodes()),
-            basic_coverage_blocks,
+            counters: CoverageCounters::with_num_bcbs(graph.num_nodes()),
+            graph,
             bcb_needs_counter,
         }
     }
@@ -295,7 +282,7 @@ impl<'a> MakeBcbCounters<'a> {
         // nodes within the loop are visited before visiting any nodes outside
         // the loop. It also keeps track of which loop(s) the traversal is
         // currently inside.
-        let mut traversal = TraverseCoverageGraphWithLoops::new(self.basic_coverage_blocks);
+        let mut traversal = TraverseCoverageGraphWithLoops::new(self.graph);
         while let Some(bcb) = traversal.next() {
             let _span = debug_span!("traversal", ?bcb).entered();
             if self.bcb_needs_counter.contains(bcb) {
@@ -322,25 +309,35 @@ impl<'a> MakeBcbCounters<'a> {
         // We might also use that counter to compute one of the out-edge counters.
         let node_counter = self.get_or_make_node_counter(from_bcb);
 
-        let successors = self.basic_coverage_blocks.successors[from_bcb].as_slice();
+        let successors = self.graph.successors[from_bcb].as_slice();
 
         // If this node's out-edges won't sum to the node's counter,
         // then there's no reason to create edge counters here.
-        if !self.basic_coverage_blocks[from_bcb].is_out_summable {
+        if !self.graph[from_bcb].is_out_summable {
             return;
         }
 
-        // Determine the set of out-edges that don't yet have edge counters.
-        let candidate_successors = self.basic_coverage_blocks.successors[from_bcb]
+        // When choosing which out-edge should be given a counter expression, ignore edges that
+        // already have counters, or could use the existing counter of their target node.
+        let out_edge_has_counter = |to_bcb| {
+            if self.counters.edge_counters.contains_key(&(from_bcb, to_bcb)) {
+                return true;
+            }
+            self.graph.sole_predecessor(to_bcb) == Some(from_bcb)
+                && self.counters.node_counters[to_bcb].is_some()
+        };
+
+        // Determine the set of out-edges that could benefit from being given an expression.
+        let candidate_successors = self.graph.successors[from_bcb]
             .iter()
             .copied()
-            .filter(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb))
+            .filter(|&to_bcb| !out_edge_has_counter(to_bcb))
             .collect::<Vec<_>>();
         debug!(?candidate_successors);
 
         // If there are out-edges without counters, choose one to be given an expression
         // (computed from this node and the other out-edges) instead of a physical counter.
-        let Some(expression_to_bcb) =
+        let Some(target_bcb) =
             self.choose_out_edge_for_expression(traversal, &candidate_successors)
         else {
             return;
@@ -353,43 +350,44 @@ impl<'a> MakeBcbCounters<'a> {
             .iter()
             .copied()
             // Skip the chosen edge, since we'll calculate its count from this sum.
-            .filter(|&to_bcb| to_bcb != expression_to_bcb)
+            .filter(|&edge_target_bcb| edge_target_bcb != target_bcb)
             .map(|to_bcb| self.get_or_make_edge_counter(from_bcb, to_bcb))
             .collect::<Vec<_>>();
-        let Some(sum_of_all_other_out_edges) =
-            self.coverage_counters.make_sum(&other_out_edge_counters)
+        let Some(sum_of_all_other_out_edges) = self.counters.make_sum(&other_out_edge_counters)
         else {
             return;
         };
 
         // Now create an expression for the chosen edge, by taking the counter
         // for its source node and subtracting the sum of its sibling out-edges.
-        let expression = self.coverage_counters.make_expression(
-            node_counter,
-            Op::Subtract,
-            sum_of_all_other_out_edges,
-        );
+        let expression =
+            self.counters.make_expression(node_counter, Op::Subtract, sum_of_all_other_out_edges);
 
-        debug!("{expression_to_bcb:?} gets an expression: {expression:?}");
-        if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(expression_to_bcb) {
-            // This edge normally wouldn't get its own counter, so attach the expression
-            // to its target node instead, so that `edge_has_no_counter` can see it.
-            assert_eq!(sole_pred, from_bcb);
-            self.coverage_counters.set_bcb_counter(expression_to_bcb, expression);
-        } else {
-            self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
-        }
+        debug!("{target_bcb:?} gets an expression: {expression:?}");
+        self.counters.set_edge_counter(from_bcb, target_bcb, expression);
     }
 
     #[instrument(level = "debug", skip(self))]
     fn get_or_make_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
         // If the BCB already has a counter, return it.
-        if let Some(counter_kind) = self.coverage_counters.bcb_counters[bcb] {
-            debug!("{bcb:?} already has a counter: {counter_kind:?}");
-            return counter_kind;
+        if let Some(counter) = self.counters.node_counters[bcb] {
+            debug!("{bcb:?} already has a counter: {counter:?}");
+            return counter;
+        }
+
+        let counter = self.make_node_counter_inner(bcb);
+        self.counters.set_node_counter(bcb, counter)
+    }
+
+    fn make_node_counter_inner(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
+        // If the node's sole in-edge already has a counter, use that.
+        if let Some(sole_pred) = self.graph.sole_predecessor(bcb)
+            && let Some(&edge_counter) = self.counters.edge_counters.get(&(sole_pred, bcb))
+        {
+            return edge_counter;
         }
 
-        let predecessors = self.basic_coverage_blocks.predecessors[bcb].as_slice();
+        let predecessors = self.graph.predecessors[bcb].as_slice();
 
         // Handle cases where we can't compute a node's count from its in-edges:
         // - START_BCB has no in-edges, so taking the sum would panic (or be wrong).
@@ -398,7 +396,9 @@ impl<'a> MakeBcbCounters<'a> {
         //   leading to infinite recursion.
         if predecessors.len() <= 1 || predecessors.contains(&bcb) {
             debug!(?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor");
-            return self.coverage_counters.make_phys_node_counter(bcb);
+            let counter = self.counters.make_phys_node_counter(bcb);
+            debug!(?bcb, ?counter, "node gets a physical counter");
+            return counter;
         }
 
         // A BCB with multiple incoming edges can compute its count by ensuring that counters
@@ -408,13 +408,11 @@ impl<'a> MakeBcbCounters<'a> {
             .copied()
             .map(|from_bcb| self.get_or_make_edge_counter(from_bcb, bcb))
             .collect::<Vec<_>>();
-        let sum_of_in_edges: BcbCounter = self
-            .coverage_counters
-            .make_sum(&in_edge_counters)
-            .expect("there must be at least one in-edge");
+        let sum_of_in_edges: BcbCounter =
+            self.counters.make_sum(&in_edge_counters).expect("there must be at least one in-edge");
 
         debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}");
-        self.coverage_counters.set_bcb_counter(bcb, sum_of_in_edges)
+        sum_of_in_edges
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -423,9 +421,24 @@ impl<'a> MakeBcbCounters<'a> {
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
     ) -> BcbCounter {
+        // If the edge already has a counter, return it.
+        if let Some(&counter) = self.counters.edge_counters.get(&(from_bcb, to_bcb)) {
+            debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter:?}");
+            return counter;
+        }
+
+        let counter = self.make_edge_counter_inner(from_bcb, to_bcb);
+        self.counters.set_edge_counter(from_bcb, to_bcb, counter)
+    }
+
+    fn make_edge_counter_inner(
+        &mut self,
+        from_bcb: BasicCoverageBlock,
+        to_bcb: BasicCoverageBlock,
+    ) -> BcbCounter {
         // If the target node has exactly one in-edge (i.e. this one), then just
         // use the node's counter, since it will have the same value.
-        if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(to_bcb) {
+        if let Some(sole_pred) = self.graph.sole_predecessor(to_bcb) {
             assert_eq!(sole_pred, from_bcb);
             // This call must take care not to invoke `get_or_make_edge` for
             // this edge, since that would result in infinite recursion!
@@ -434,21 +447,15 @@ impl<'a> MakeBcbCounters<'a> {
 
         // If the source node has exactly one out-edge (i.e. this one) and would have
         // the same execution count as that edge, then just use the node's counter.
-        if let Some(simple_succ) = self.basic_coverage_blocks.simple_successor(from_bcb) {
+        if let Some(simple_succ) = self.graph.simple_successor(from_bcb) {
             assert_eq!(simple_succ, to_bcb);
             return self.get_or_make_node_counter(from_bcb);
         }
 
-        // If the edge already has a counter, return it.
-        if let Some(&counter_kind) =
-            self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
-        {
-            debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}");
-            return counter_kind;
-        }
-
         // Make a new counter to count this edge.
-        self.coverage_counters.make_phys_edge_counter(from_bcb, to_bcb)
+        let counter = self.counters.make_phys_edge_counter(from_bcb, to_bcb);
+        debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
+        counter
     }
 
     /// Given a set of candidate out-edges (represented by their successor node),
@@ -493,9 +500,9 @@ impl<'a> MakeBcbCounters<'a> {
             for &target_bcb in candidate_successors {
                 // An edge is a reloop edge if its target dominates any BCB that has
                 // an edge back to the loop header. (Otherwise it's an exit edge.)
-                let is_reloop_edge = reloop_bcbs.iter().any(|&reloop_bcb| {
-                    self.basic_coverage_blocks.dominates(target_bcb, reloop_bcb)
-                });
+                let is_reloop_edge = reloop_bcbs
+                    .iter()
+                    .any(|&reloop_bcb| self.graph.dominates(target_bcb, reloop_bcb));
                 if is_reloop_edge {
                     // We found a good out-edge to be given an expression.
                     return Some(target_bcb);
@@ -508,21 +515,4 @@ impl<'a> MakeBcbCounters<'a> {
 
         None
     }
-
-    #[inline]
-    fn edge_has_no_counter(
-        &self,
-        from_bcb: BasicCoverageBlock,
-        to_bcb: BasicCoverageBlock,
-    ) -> bool {
-        let edge_counter =
-            if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(to_bcb) {
-                assert_eq!(sole_pred, from_bcb);
-                self.coverage_counters.bcb_counters[to_bcb]
-            } else {
-                self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)).copied()
-            };
-
-        edge_counter.is_none()
-    }
 }
diff --git a/src/doc/rustc/src/platform-support/nuttx.md b/src/doc/rustc/src/platform-support/nuttx.md
index cbbede45f52..433a092aab2 100644
--- a/src/doc/rustc/src/platform-support/nuttx.md
+++ b/src/doc/rustc/src/platform-support/nuttx.md
@@ -35,7 +35,7 @@ The following target names are defined:
 
 ## Building the target
 
-The target can be built by enabled in the `rustc` build:
+The target can be built by enabling it in the `rustc` build:
 
 ```toml
 [build]
diff --git a/src/tools/rust-analyzer/.editorconfig b/src/tools/rust-analyzer/.editorconfig
index e337066f7ea..6bb743a6736 100644
--- a/src/tools/rust-analyzer/.editorconfig
+++ b/src/tools/rust-analyzer/.editorconfig
@@ -13,5 +13,5 @@ max_line_length = 100
 [*.md]
 indent_size = 2
 
-[*.{yml, yaml}]
+[*.{yml,yaml}]
 indent_size = 2
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 6d3e488bb08..5cf4a8fd439 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -104,11 +104,11 @@ jobs:
         if: matrix.os == 'ubuntu-latest'
         run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats .
 
-      - name: Run analysis-stats on rust std library
+      - name: Run analysis-stats on the rust standard libraries
         if: matrix.os == 'ubuntu-latest'
         env:
-          RUSTC_BOOTSTRAP: 1
-        run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std
+            RUSTC_BOOTSTRAP: 1
+        run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/
 
       - name: clippy
         if: matrix.os == 'windows-latest'
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 4a6da47a47d..fd569571b38 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -73,7 +73,7 @@ dependencies = [
  "intern",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lz4_flex",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "salsa",
  "semver",
  "span",
@@ -161,7 +161,7 @@ dependencies = [
  "expect-test",
  "intern",
  "oorandom",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "syntax",
  "syntax-bridge",
  "tt",
@@ -216,7 +216,7 @@ dependencies = [
  "chalk-derive",
  "chalk-ir",
  "chalk-solve",
- "rustc-hash",
+ "rustc-hash 1.1.0",
  "tracing",
 ]
 
@@ -232,7 +232,7 @@ dependencies = [
  "indexmap",
  "itertools",
  "petgraph",
- "rustc-hash",
+ "rustc-hash 1.1.0",
  "tracing",
 ]
 
@@ -513,7 +513,7 @@ dependencies = [
  "hir-ty",
  "intern",
  "itertools",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "smallvec",
  "span",
  "stdx",
@@ -547,7 +547,7 @@ dependencies = [
  "mbe",
  "ra-ap-rustc_abi",
  "ra-ap-rustc_parse_format",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "rustc_apfloat",
  "smallvec",
  "span",
@@ -577,7 +577,7 @@ dependencies = [
  "limit",
  "mbe",
  "parser",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "smallvec",
  "span",
  "stdx",
@@ -616,7 +616,7 @@ dependencies = [
  "ra-ap-rustc_abi",
  "ra-ap-rustc_index",
  "ra-ap-rustc_pattern_analysis",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "rustc_apfloat",
  "scoped-tls",
  "smallvec",
@@ -731,13 +731,13 @@ dependencies = [
  "indexmap",
  "itertools",
  "limit",
- "line-index 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr",
  "nohash-hasher",
  "parser",
  "profile",
  "rayon",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "span",
  "stdx",
  "syntax",
@@ -834,7 +834,7 @@ version = "0.0.0"
 dependencies = [
  "dashmap",
  "hashbrown",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "sptr",
  "triomphe",
 ]
@@ -939,7 +939,7 @@ version = "0.0.0"
 
 [[package]]
 name = "line-index"
-version = "0.1.1"
+version = "0.1.2"
 dependencies = [
  "nohash-hasher",
  "oorandom",
@@ -948,9 +948,9 @@ dependencies = [
 
 [[package]]
 name = "line-index"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67d61795376ae2683928c218fda7d7d7db136fd38c06b7552904667f0d55580a"
+checksum = "3e27e0ed5a392a7f5ba0b3808a2afccff16c64933312c84b57618b49d1209bd2"
 dependencies = [
  "nohash-hasher",
  "text-size",
@@ -1051,7 +1051,7 @@ dependencies = [
  "intern",
  "parser",
  "ra-ap-rustc_lexer",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "smallvec",
  "span",
  "stdx",
@@ -1345,7 +1345,7 @@ dependencies = [
  "indexmap",
  "intern",
  "paths",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "serde",
  "serde_json",
  "span",
@@ -1435,7 +1435,7 @@ dependencies = [
  "itertools",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "paths",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "semver",
  "serde",
  "serde_json",
@@ -1497,9 +1497,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.71.0"
+version = "0.73.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6999d098000b98415939f13158dac78cb3eeeb7b0c073847f3e4b623866e27c"
+checksum = "879ece0781e3c1cb670b9f29775c81a43a16db789d1296fad6bc5c74065b2fac"
 dependencies = [
  "bitflags 2.6.0",
  "ra-ap-rustc_index",
@@ -1508,9 +1508,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.71.0"
+version = "0.73.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae9fb312d942817dab10790881f555928c1f6a11a85186e8e573ad4a86c7d3be"
+checksum = "6910087ff89bb9f3db114bfcd86b5139042731fe7278d3ff4ceaa69a140154a7"
 dependencies = [
  "arrayvec",
  "ra-ap-rustc_index_macros",
@@ -1519,9 +1519,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.71.0"
+version = "0.73.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "766e3990eb1066a06deefc561b5a01b32ca5c9211feea31cbf4ed50611519872"
+checksum = "3b6f7bd12b678fbb37444ba77f3b0cfc13b7394a6dc7b0c799491fc9df0a9997"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1530,9 +1530,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.71.0"
+version = "0.73.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4afa98eb7889c137d5a3f1cd189089e16da04d1e4837d358a67aa3dab10ffbe"
+checksum = "119bc05b5b6bc3e7f5b67ce8b8080e185da94bd83c447f91b6b3f3ecf60cbab1"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1540,9 +1540,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.71.0"
+version = "0.73.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9234c96ffb0565286790407fb7eb7f55ebf69267de4db382fdec0a17f14b0e2"
+checksum = "70ed6150ae71d905c064dc88d7824ebb0fa81083f45d7477cba7b57176f2f635"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1550,12 +1550,12 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.71.0"
+version = "0.73.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "273d5f72926a58c7eea27aebc898d1d5b32d23d2342f692a94a2cf8746aa4a2f"
+checksum = "6e830862a0ec85fce211d34735315686bb8d6a12d418d6d735fb534aa1cd3293"
 dependencies = [
  "ra-ap-rustc_index",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "rustc_apfloat",
  "smallvec",
  "tracing",
@@ -1640,7 +1640,7 @@ dependencies = [
  "countme",
  "hashbrown",
  "memoffset",
- "rustc-hash",
+ "rustc-hash 1.1.0",
  "text-size",
 ]
 
@@ -1680,7 +1680,7 @@ dependencies = [
  "profile",
  "project-model",
  "rayon",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "scip",
  "semver",
  "serde",
@@ -1718,6 +1718,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
+name = "rustc-hash"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
+
+[[package]]
 name = "rustc_apfloat"
 version = "0.2.1+llvm-462a31f5a5ab"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1746,7 +1752,7 @@ dependencies = [
  "oorandom",
  "parking_lot",
  "rand",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "salsa-macros",
  "smallvec",
  "tracing",
@@ -1898,7 +1904,7 @@ version = "0.0.0"
 dependencies = [
  "hashbrown",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "salsa",
  "stdx",
  "syntax",
@@ -1967,7 +1973,7 @@ dependencies = [
  "ra-ap-rustc_lexer",
  "rayon",
  "rowan",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "rustc_apfloat",
  "smol_str",
  "stdx",
@@ -1983,7 +1989,7 @@ version = "0.0.0"
 dependencies = [
  "intern",
  "parser",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "span",
  "stdx",
  "syntax",
@@ -2000,7 +2006,7 @@ dependencies = [
  "cfg",
  "hir-expand",
  "intern",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "span",
  "stdx",
  "test-utils",
@@ -2014,7 +2020,7 @@ dependencies = [
  "dissimilar",
  "paths",
  "profile",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "stdx",
  "text-size",
  "tracing",
@@ -2361,7 +2367,7 @@ dependencies = [
  "indexmap",
  "nohash-hasher",
  "paths",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "stdx",
  "tracing",
 ]
@@ -2374,7 +2380,7 @@ dependencies = [
  "notify",
  "paths",
  "rayon",
- "rustc-hash",
+ "rustc-hash 2.0.0",
  "stdx",
  "tracing",
  "vfs",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 8c099f324b4..9db62de9abf 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -85,18 +85,18 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.71.0", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.71.0", default-features = false }
-ra-ap-rustc_index = { version = "0.71.0", default-features = false }
-ra-ap-rustc_abi = { version = "0.71.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.71.0", default-features = false }
+ra-ap-rustc_lexer = { version = "0.73", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.73", default-features = false }
+ra-ap-rustc_index = { version = "0.73", default-features = false }
+ra-ap-rustc_abi = { version = "0.73", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.73", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 test-fixture = { path = "./crates/test-fixture" }
 test-utils = { path = "./crates/test-utils" }
 
 # In-tree crates that are published separately and follow semver. See lib/README.md
-line-index = { version = "0.1.1" }
+line-index = { version = "0.1.2" }
 la-arena = { version = "0.3.1" }
 lsp-server = { version = "0.7.6" }
 
@@ -136,7 +136,7 @@ process-wrap = { version = "8.0.2", features = ["std"] }
 pulldown-cmark-to-cmark = "10.0.4"
 pulldown-cmark = { version = "0.9.0", default-features = false }
 rayon = "1.8.0"
-rustc-hash = "1.1.0"
+rustc-hash = "2.0.0"
 semver = "1.0.14"
 serde = { version = "1.0.192", features = ["derive"] }
 serde_json = "1.0.108"
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 3ecb57c7567..263fad51d78 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -148,6 +148,10 @@ impl FunctionData {
         self.flags.contains(FnFlags::HAS_UNSAFE_KW)
     }
 
+    pub fn is_safe(&self) -> bool {
+        self.flags.contains(FnFlags::HAS_SAFE_KW)
+    }
+
     pub fn is_varargs(&self) -> bool {
         self.flags.contains(FnFlags::IS_VARARGS)
     }
@@ -567,6 +571,8 @@ pub struct StaticData {
     pub visibility: RawVisibility,
     pub mutable: bool,
     pub is_extern: bool,
+    pub has_safe_kw: bool,
+    pub has_unsafe_kw: bool,
 }
 
 impl StaticData {
@@ -581,6 +587,8 @@ impl StaticData {
             visibility: item_tree[statik.visibility].clone(),
             mutable: statik.mutable,
             is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
+            has_safe_kw: statik.has_safe_kw,
+            has_unsafe_kw: statik.has_unsafe_kw,
         })
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index f16230e1dc3..7cb833fdce7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -754,6 +754,7 @@ bitflags::bitflags! {
         const HAS_ASYNC_KW = 1 << 4;
         const HAS_UNSAFE_KW = 1 << 5;
         const IS_VARARGS = 1 << 6;
+        const HAS_SAFE_KW = 1 << 7;
     }
 }
 
@@ -822,7 +823,10 @@ pub struct Const {
 pub struct Static {
     pub name: Name,
     pub visibility: RawVisibilityId,
+    // TODO: use bitflags when we have more flags
     pub mutable: bool,
+    pub has_safe_kw: bool,
+    pub has_unsafe_kw: bool,
     pub type_ref: Interned<TypeRef>,
     pub ast_id: FileAstId<ast::Static>,
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index 7aac383ab47..431a7f66f40 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -440,6 +440,9 @@ impl<'a> Ctx<'a> {
         if func.unsafe_token().is_some() {
             flags |= FnFlags::HAS_UNSAFE_KW;
         }
+        if func.safe_token().is_some() {
+            flags |= FnFlags::HAS_SAFE_KW;
+        }
         if has_var_args {
             flags |= FnFlags::IS_VARARGS;
         }
@@ -484,8 +487,11 @@ impl<'a> Ctx<'a> {
         let type_ref = self.lower_type_ref_opt(static_.ty());
         let visibility = self.lower_visibility(static_);
         let mutable = static_.mut_token().is_some();
+        let has_safe_kw = static_.safe_token().is_some();
+        let has_unsafe_kw = static_.unsafe_token().is_some();
         let ast_id = self.source_ast_id_map.ast_id(static_);
-        let res = Static { name, visibility, mutable, type_ref, ast_id };
+        let res =
+            Static { name, visibility, mutable, type_ref, ast_id, has_safe_kw, has_unsafe_kw };
         Some(id(self.data().statics.alloc(res)))
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index b5a65abce86..9dce28b2e49 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -278,6 +278,9 @@ impl Printer<'_> {
                 if flags.contains(FnFlags::HAS_UNSAFE_KW) {
                     w!(self, "unsafe ");
                 }
+                if flags.contains(FnFlags::HAS_SAFE_KW) {
+                    w!(self, "safe ");
+                }
                 if let Some(abi) = abi {
                     w!(self, "extern \"{}\" ", abi);
                 }
@@ -379,9 +382,23 @@ impl Printer<'_> {
                 wln!(self, " = _;");
             }
             ModItem::Static(it) => {
-                let Static { name, visibility, mutable, type_ref, ast_id } = &self.tree[it];
+                let Static {
+                    name,
+                    visibility,
+                    mutable,
+                    type_ref,
+                    ast_id,
+                    has_safe_kw,
+                    has_unsafe_kw,
+                } = &self.tree[it];
                 self.print_ast_id(ast_id.erase());
                 self.print_visibility(*visibility);
+                if *has_safe_kw {
+                    w!(self, "safe ");
+                }
+                if *has_unsafe_kw {
+                    w!(self, "unsafe ");
+                }
                 w!(self, "static ");
                 if *mutable {
                     w!(self, "mut ");
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
index 11d91513f12..3aeb88047a0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
@@ -139,13 +139,11 @@ impl Visibility {
         let def_map_block = def_map.block_id();
         loop {
             match (to_module.block, def_map_block) {
-                // to_module is not a block, so there is no parent def map to use
+                // `to_module` is not a block, so there is no parent def map to use.
                 (None, _) => (),
+                // `to_module` is at `def_map`'s block, no need to move further.
                 (Some(a), Some(b)) if a == b => {
                     cov_mark::hit!(is_visible_from_same_block_def_map);
-                    if let Some(parent) = def_map.parent() {
-                        to_module = parent;
-                    }
                 }
                 _ => {
                     if let Some(parent) = to_module.def_map(db).parent() {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index d04225b8722..4894c7a9311 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -5,19 +5,20 @@ use cfg::CfgExpr;
 use either::Either;
 use intern::{sym, Symbol};
 use mbe::{expect_fragment, DelimiterKind};
-use span::{Edition, EditionedFileId, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
+use span::{Edition, EditionedFileId, Span};
 use stdx::format_to;
 use syntax::{
     format_smolstr,
     unescape::{unescape_byte, unescape_char, unescape_unicode, Mode},
 };
-use syntax_bridge::parse_to_token_tree;
+use syntax_bridge::syntax_node_to_token_tree;
 
 use crate::{
     builtin::quote::{dollar_crate, quote},
     db::ExpandDatabase,
     hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
     name,
+    span_map::SpanMap,
     tt::{self, DelimSpan},
     ExpandError, ExpandResult, HirFileIdExt, Lookup as _, MacroCallId,
 };
@@ -739,18 +740,14 @@ fn include_expand(
             return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
         }
     };
-    match parse_to_token_tree(
-        file_id.edition(),
-        SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
-        SyntaxContextId::ROOT,
-        &db.file_text(file_id.file_id()),
-    ) {
-        Some(it) => ExpandResult::ok(it),
-        None => ExpandResult::new(
-            tt::Subtree::empty(DelimSpan { open: span, close: span }),
-            ExpandError::other(span, "failed to parse included file"),
-        ),
-    }
+    let span_map = db.real_span_map(file_id);
+    // FIXME: Parse errors
+    ExpandResult::ok(syntax_node_to_token_tree(
+        &db.parse(file_id).syntax_node(),
+        SpanMap::RealSpanMap(span_map),
+        span,
+        syntax_bridge::DocCommentDesugarMode::ProcMacro,
+    ))
 }
 
 pub fn include_input_to_file_id(
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index d412bf4eee5..0d19ae202ce 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -35,7 +35,7 @@ type MacroArgResult = (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span);
 /// an error will be emitted.
 ///
 /// Actual max for `analysis-stats .` at some point: 30672.
-static TOKEN_LIMIT: Limit = Limit::new(1_048_576);
+static TOKEN_LIMIT: Limit = Limit::new(2_097_152);
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum TokenExpander {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 7093fcadcb0..0a8bfaa70f8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -95,7 +95,8 @@ fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8], &MemoryMap)) {
 fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
     let mut err = String::new();
     let span_formatter = |file, range| format!("{file:?} {range:?}");
-    let edition = db.crate_graph()[db.test_crate()].edition;
+    let edition =
+        db.crate_graph()[*db.crate_graph().crates_in_topological_order().last().unwrap()].edition;
     match e {
         ConstEvalError::MirLowerError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
         ConstEvalError::MirEvalError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
@@ -2896,7 +2897,7 @@ fn recursive_adt() {
                 {
                     const VARIANT_TAG_TREE: TagTree = TagTree::Choice(
                         &[
-                            TagTree::Leaf,
+                            TAG_TREE,
                         ],
                     );
                     VARIANT_TAG_TREE
@@ -2905,6 +2906,6 @@ fn recursive_adt() {
             TAG_TREE
         };
     "#,
-        |e| matches!(e, ConstEvalError::MirEvalError(MirEvalError::StackOverflow)),
+        |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::Loop)),
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
index ff45c725c73..bcfc37c8671 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -89,7 +89,7 @@ fn walk_unsafe(
             let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
             if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
                 let static_data = db.static_data(id);
-                if static_data.mutable || static_data.is_extern {
+                if static_data.mutable || (static_data.is_extern && !static_data.has_safe_kw) {
                     unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index 7300453ff00..e4881d75201 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -917,9 +917,19 @@ impl<'a> InferenceTable<'a> {
     /// Check if given type is `Sized` or not
     pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool {
         // Early return for some obvious types
-        if matches!(ty.kind(Interner), TyKind::Scalar(..) | TyKind::Ref(..) | TyKind::Raw(..)) {
+        if matches!(
+            ty.kind(Interner),
+            TyKind::Scalar(..)
+                | TyKind::Ref(..)
+                | TyKind::Raw(..)
+                | TyKind::Never
+                | TyKind::FnDef(..)
+                | TyKind::Array(..)
+                | TyKind::Function(_)
+        ) {
             return true;
         }
+
         if let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
             let struct_data = self.db.struct_data(id);
             if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 2c68d50013e..80831440720 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -72,18 +72,15 @@ pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx
 
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub enum LayoutError {
-    // FIXME: Remove variants that duplicate LayoutCalculatorError's variants after sync
+    // FIXME: Remove more variants once they get added to LayoutCalculatorError
     BadCalc(LayoutCalculatorError<()>),
-    EmptyUnion,
     HasErrorConst,
     HasErrorType,
     HasPlaceholder,
     InvalidSimdType,
     NotImplemented,
     RecursiveTypeWithoutIndirection,
-    SizeOverflow,
     TargetLayoutNotAvailable,
-    UnexpectedUnsized,
     Unknown,
     UserReprTooSmall,
 }
@@ -93,7 +90,6 @@ impl fmt::Display for LayoutError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             LayoutError::BadCalc(err) => err.fallback_fmt(f),
-            LayoutError::EmptyUnion => write!(f, "type is an union with no fields"),
             LayoutError::HasErrorConst => write!(f, "type contains an unevaluatable const"),
             LayoutError::HasErrorType => write!(f, "type contains an error"),
             LayoutError::HasPlaceholder => write!(f, "type contains placeholders"),
@@ -102,11 +98,7 @@ impl fmt::Display for LayoutError {
             LayoutError::RecursiveTypeWithoutIndirection => {
                 write!(f, "recursive type without indirection")
             }
-            LayoutError::SizeOverflow => write!(f, "size overflow"),
             LayoutError::TargetLayoutNotAvailable => write!(f, "target layout not available"),
-            LayoutError::UnexpectedUnsized => {
-                write!(f, "an unsized type was found where a sized type was expected")
-            }
             LayoutError::Unknown => write!(f, "unknown"),
             LayoutError::UserReprTooSmall => {
                 write!(f, "the `#[repr]` hint is too small to hold the discriminants of the enum")
@@ -181,7 +173,10 @@ fn layout_of_simd_ty(
     };
 
     // Compute the size and alignment of the vector:
-    let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow)?;
+    let size = e_ly
+        .size
+        .checked_mul(e_len, dl)
+        .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
     let align = dl.vector_align(size);
     let size = size.align_to(align.abi);
 
@@ -294,7 +289,10 @@ pub fn layout_of_ty_query(
         TyKind::Array(element, count) => {
             let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64;
             let element = db.layout_of_ty(element.clone(), trait_env)?;
-            let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;
+            let size = element
+                .size
+                .checked_mul(count, dl)
+                .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
 
             let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
                 Abi::Uninhabited
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 649cf88bb8d..9c1d8bcf36f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -51,10 +51,7 @@ mod test_db;
 #[cfg(test)]
 mod tests;
 
-use std::{
-    collections::hash_map::Entry,
-    hash::{BuildHasherDefault, Hash},
-};
+use std::hash::Hash;
 
 use base_db::ra_salsa::InternValueTrivial;
 use chalk_ir::{
@@ -65,10 +62,11 @@ use chalk_ir::{
 use either::Either;
 use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId};
 use hir_expand::name::Name;
+use indexmap::{map::Entry, IndexMap};
 use intern::{sym, Symbol};
 use la_arena::{Arena, Idx};
 use mir::{MirEvalError, VTableMap};
-use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
 use span::Edition;
 use syntax::ast::{make, ConstArg};
 use traits::FnTrait;
@@ -199,7 +197,7 @@ pub enum MemoryMap {
 
 #[derive(Debug, Default, Clone, PartialEq, Eq)]
 pub struct ComplexMemoryMap {
-    memory: FxHashMap<usize, Box<[u8]>>,
+    memory: IndexMap<usize, Box<[u8]>, FxBuildHasher>,
     vtable: VTableMap,
 }
 
@@ -245,7 +243,7 @@ impl MemoryMap {
         match self {
             MemoryMap::Empty => Ok(Default::default()),
             MemoryMap::Simple(m) => transform((&0, m)).map(|(addr, val)| {
-                let mut map = FxHashMap::with_capacity_and_hasher(1, BuildHasherDefault::default());
+                let mut map = FxHashMap::with_capacity_and_hasher(1, rustc_hash::FxBuildHasher);
                 map.insert(addr, val);
                 map
             }),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index d1ce68da6d6..620bba2d75c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -257,10 +257,12 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
         return true;
     }
 
-    match func.lookup(db.upcast()).container {
+    let loc = func.lookup(db.upcast());
+    match loc.container {
         hir_def::ItemContainerId::ExternBlockId(block) => {
-            // Function in an `extern` block are always unsafe to call, except when it has
-            // `"rust-intrinsic"` ABI there are a few exceptions.
+            // Function in an `extern` block are always unsafe to call, except when
+            // it is marked as `safe` or it has `"rust-intrinsic"` ABI there are a
+            // few exceptions.
             let id = block.lookup(db.upcast()).id;
 
             let is_intrinsic =
@@ -270,8 +272,8 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
                 // Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
                 !data.attrs.by_key(&sym::rustc_safe_intrinsic).exists()
             } else {
-                // Extern items are always unsafe
-                true
+                // Extern items without `safe` modifier are always unsafe
+                !data.is_safe()
             }
         }
         _ => false,
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index b27f1fbb5db..3eac33ce990 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -892,29 +892,8 @@ impl<'db> SemanticsImpl<'db> {
         f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContextId) -> ControlFlow<T>,
     ) -> Option<T> {
         let _p = tracing::info_span!("descend_into_macros_impl").entered();
-        let (sa, span, file_id) = token
-            .parent()
-            .and_then(|parent| {
-                self.analyze_impl(InRealFile::new(file_id, &parent).into(), None, false)
-            })
-            .and_then(|sa| {
-                let file_id = sa.file_id.file_id()?;
-                Some((
-                    sa,
-                    self.db.real_span_map(file_id).span_for_range(token.text_range()),
-                    HirFileId::from(file_id),
-                ))
-            })?;
 
-        let mut m_cache = self.macro_call_cache.borrow_mut();
-        let def_map = sa.resolver.def_map();
-
-        // A stack of tokens to process, along with the file they came from
-        // These are tracked to know which macro calls we still have to look into
-        // the tokens themselves aren't that interesting as the span that is being used to map
-        // things down never changes.
-        let mut stack: Vec<(_, SmallVec<[_; 2]>)> =
-            vec![(file_id, smallvec![(token, SyntaxContextId::ROOT)])];
+        let span = self.db.real_span_map(file_id).span_for_range(token.text_range());
 
         // Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
         let process_expansion_for_token = |stack: &mut Vec<_>, macro_file| {
@@ -926,7 +905,6 @@ impl<'db> SemanticsImpl<'db> {
                         .map(SmallVec::<[_; 2]>::from_iter),
                 )
             })?;
-
             // we have found a mapping for the token if the vec is non-empty
             let res = mapped_tokens.is_empty().not().then_some(());
             // requeue the tokens we got from mapping our current token down
@@ -934,6 +912,33 @@ impl<'db> SemanticsImpl<'db> {
             res
         };
 
+        // A stack of tokens to process, along with the file they came from
+        // These are tracked to know which macro calls we still have to look into
+        // the tokens themselves aren't that interesting as the span that is being used to map
+        // things down never changes.
+        let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![];
+        let include = self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, file_id);
+        match include {
+            Some(include) => {
+                // include! inputs are always from real files, so they only need to be handled once upfront
+                process_expansion_for_token(&mut stack, include)?;
+            }
+            None => {
+                stack.push((file_id.into(), smallvec![(token, SyntaxContextId::ROOT)]));
+            }
+        }
+
+        let (file_id, tokens) = stack.first()?;
+        // make sure we pick the token in the expanded include if we encountered an include,
+        // otherwise we'll get the wrong semantics
+        let sa =
+            tokens.first()?.0.parent().and_then(|parent| {
+                self.analyze_impl(InFile::new(*file_id, &parent), None, false)
+            })?;
+
+        let mut m_cache = self.macro_call_cache.borrow_mut();
+        let def_map = sa.resolver.def_map();
+
         // Filters out all tokens that contain the given range (usually the macro call), any such
         // token is redundant as the corresponding macro call has already been processed
         let filter_duplicates = |tokens: &mut SmallVec<_>, range: TextRange| {
@@ -1011,6 +1016,7 @@ impl<'db> SemanticsImpl<'db> {
                                         ) {
                                         call.as_macro_file()
                                     } else {
+                                        // FIXME: This is wrong, the SourceAnalyzer might be invalid here
                                         sa.expand(self.db, mcall.as_ref())?
                                     };
                                     m_cache.insert(mcall, it);
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index fd6d52d6c9d..389778b44ed 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -104,7 +104,7 @@ use hir_expand::{
 };
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
-use span::{FileId, MacroFileId};
+use span::{EditionedFileId, FileId, MacroFileId};
 use stdx::impl_from;
 use syntax::{
     ast::{self, HasName},
@@ -118,9 +118,27 @@ pub(super) struct SourceToDefCache {
     pub(super) dynmap_cache: FxHashMap<(ChildContainer, HirFileId), DynMap>,
     expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>,
     pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>,
+    pub(super) included_file_cache: FxHashMap<EditionedFileId, Option<MacroFileId>>,
 }
 
 impl SourceToDefCache {
+    pub(super) fn get_or_insert_include_for(
+        &mut self,
+        db: &dyn HirDatabase,
+        file: EditionedFileId,
+    ) -> Option<MacroFileId> {
+        if let Some(&m) = self.included_file_cache.get(&file) {
+            return m;
+        }
+        self.included_file_cache.insert(file, None);
+        for &crate_id in db.relevant_crates(file.into()).iter() {
+            db.include_macro_invoc(crate_id).iter().for_each(|&(macro_call_id, file_id)| {
+                self.included_file_cache.insert(file_id, Some(MacroFileId { macro_call_id }));
+            });
+        }
+        self.included_file_cache.get(&file).copied().flatten()
+    }
+
     pub(super) fn get_or_insert_expansion(
         &mut self,
         sema: &SemanticsImpl<'_>,
@@ -163,9 +181,13 @@ impl SourceToDefCtx<'_, '_> {
                             .include_macro_invoc(crate_id)
                             .iter()
                             .filter(|&&(_, file_id)| file_id == file)
-                            .flat_map(|(call, _)| {
+                            .flat_map(|&(macro_call_id, file_id)| {
+                                self.cache
+                                    .included_file_cache
+                                    .insert(file_id, Some(MacroFileId { macro_call_id }));
                                 modules(
-                                    call.lookup(self.db.upcast())
+                                    macro_call_id
+                                        .lookup(self.db.upcast())
                                         .kind
                                         .file_id()
                                         .original_file(self.db.upcast())
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
index cd5fe0f8626..c035c59ffca 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
@@ -1095,6 +1095,7 @@ fn main() {
 
     #[test]
     fn field_enum_cross_file() {
+        // FIXME: The import is missing
         check_assist(
             bool_to_enum,
             r#"
@@ -1132,7 +1133,7 @@ fn foo() {
 }
 
 //- /main.rs
-use foo::{Bool, Foo};
+use foo::Foo;
 
 mod foo;
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs
deleted file mode 100644
index a1987247cb6..00000000000
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs
+++ /dev/null
@@ -1,1115 +0,0 @@
-use ide_db::{
-    famous_defs::FamousDefs,
-    syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
-};
-use itertools::Itertools;
-use syntax::{
-    ast::{self, Expr, HasGenericArgs},
-    match_ast, AstNode, NodeOrToken, SyntaxKind, TextRange,
-};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists};
-
-// Assist: unwrap_result_return_type
-//
-// Unwrap the function's return type.
-//
-// ```
-// # //- minicore: result
-// fn foo() -> Result<i32>$0 { Ok(42i32) }
-// ```
-// ->
-// ```
-// fn foo() -> i32 { 42i32 }
-// ```
-pub(crate) fn unwrap_result_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
-    let parent = ret_type.syntax().parent()?;
-    let body = match_ast! {
-        match parent {
-            ast::Fn(func) => func.body()?,
-            ast::ClosureExpr(closure) => match closure.body()? {
-                Expr::BlockExpr(block) => block,
-                // closures require a block when a return type is specified
-                _ => return None,
-            },
-            _ => return None,
-        }
-    };
-
-    let type_ref = &ret_type.ty()?;
-    let Some(hir::Adt::Enum(ret_enum)) = ctx.sema.resolve_type(type_ref)?.as_adt() else {
-        return None;
-    };
-    let result_enum =
-        FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?;
-    if ret_enum != result_enum {
-        return None;
-    }
-
-    let ok_type = unwrap_result_type(type_ref)?;
-
-    acc.add(
-        AssistId("unwrap_result_return_type", AssistKind::RefactorRewrite),
-        "Unwrap Result return type",
-        type_ref.syntax().text_range(),
-        |builder| {
-            let body = ast::Expr::BlockExpr(body);
-
-            let mut exprs_to_unwrap = Vec::new();
-            let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_unwrap, e);
-            walk_expr(&body, &mut |expr| {
-                if let Expr::ReturnExpr(ret_expr) = expr {
-                    if let Some(ret_expr_arg) = &ret_expr.expr() {
-                        for_each_tail_expr(ret_expr_arg, tail_cb);
-                    }
-                }
-            });
-            for_each_tail_expr(&body, tail_cb);
-
-            let is_unit_type = is_unit_type(&ok_type);
-            if is_unit_type {
-                let mut text_range = ret_type.syntax().text_range();
-
-                if let Some(NodeOrToken::Token(token)) = ret_type.syntax().next_sibling_or_token() {
-                    if token.kind() == SyntaxKind::WHITESPACE {
-                        text_range = TextRange::new(text_range.start(), token.text_range().end());
-                    }
-                }
-
-                builder.delete(text_range);
-            } else {
-                builder.replace(type_ref.syntax().text_range(), ok_type.syntax().text());
-            }
-
-            for ret_expr_arg in exprs_to_unwrap {
-                let ret_expr_str = ret_expr_arg.to_string();
-                if ret_expr_str.starts_with("Ok(") || ret_expr_str.starts_with("Err(") {
-                    let arg_list = ret_expr_arg.syntax().children().find_map(ast::ArgList::cast);
-                    if let Some(arg_list) = arg_list {
-                        if is_unit_type {
-                            match ret_expr_arg.syntax().prev_sibling_or_token() {
-                                // Useful to delete the entire line without leaving trailing whitespaces
-                                Some(whitespace) => {
-                                    let new_range = TextRange::new(
-                                        whitespace.text_range().start(),
-                                        ret_expr_arg.syntax().text_range().end(),
-                                    );
-                                    builder.delete(new_range);
-                                }
-                                None => {
-                                    builder.delete(ret_expr_arg.syntax().text_range());
-                                }
-                            }
-                        } else {
-                            builder.replace(
-                                ret_expr_arg.syntax().text_range(),
-                                arg_list.args().join(", "),
-                            );
-                        }
-                    }
-                }
-            }
-        },
-    )
-}
-
-fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
-    match e {
-        Expr::BreakExpr(break_expr) => {
-            if let Some(break_expr_arg) = break_expr.expr() {
-                for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
-            }
-        }
-        Expr::ReturnExpr(_) => {
-            // all return expressions have already been handled by the walk loop
-        }
-        e => acc.push(e.clone()),
-    }
-}
-
-// Tries to extract `T` from `Result<T, E>`.
-fn unwrap_result_type(ty: &ast::Type) -> Option<ast::Type> {
-    let ast::Type::PathType(path_ty) = ty else {
-        return None;
-    };
-    let path = path_ty.path()?;
-    let segment = path.first_segment()?;
-    let generic_arg_list = segment.generic_arg_list()?;
-    let generic_args: Vec<_> = generic_arg_list.generic_args().collect();
-    let ast::GenericArg::TypeArg(ok_type) = generic_args.first()? else {
-        return None;
-    };
-    ok_type.ty()
-}
-
-fn is_unit_type(ty: &ast::Type) -> bool {
-    let ast::Type::TupleType(tuple) = ty else { return false };
-    tuple.fields().next().is_none()
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
-
-    #[test]
-    fn unwrap_result_return_type_simple() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i3$02> {
-    let test = "test";
-    return Ok(42i32);
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let test = "test";
-    return 42i32;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_unit_type() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<(), Box<dyn Error$0>> {
-    Ok(())
-}
-"#,
-            r#"
-fn foo() {
-}
-"#,
-        );
-
-        // Unformatted return type
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<(), Box<dyn Error$0>>{
-    Ok(())
-}
-"#,
-            r#"
-fn foo() {
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_ending_with_parent() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32, Box<dyn Error$0>> {
-    if true {
-        Ok(42)
-    } else {
-        foo()
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    if true {
-        42
-    } else {
-        foo()
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_return_type_break_split_tail() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i3$02, String> {
-    loop {
-        break if true {
-            Ok(1)
-        } else {
-            Ok(0)
-        };
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    loop {
-        break if true {
-            1
-        } else {
-            0
-        };
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_closure() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> Result<i32$0> {
-        let test = "test";
-        return Ok(42i32);
-    };
-}
-"#,
-            r#"
-fn foo() {
-    || -> i32 {
-        let test = "test";
-        return 42i32;
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_return_type_bad_cursor() {
-        check_assist_not_applicable(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> i32 {
-    let test = "test";$0
-    return 42i32;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_return_type_bad_cursor_closure() {
-        check_assist_not_applicable(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> i32 {
-        let test = "test";$0
-        return 42i32;
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_closure_non_block() {
-        check_assist_not_applicable(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() { || -> i$032 3; }
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_return_type_already_not_result_std() {
-        check_assist_not_applicable(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let test = "test";
-    return 42i32;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_return_type_already_not_result_closure() {
-        check_assist_not_applicable(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> i32$0 {
-        let test = "test";
-        return 42i32;
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() ->$0 Result<i32> {
-    let test = "test";
-    Ok(42i32)
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let test = "test";
-    42i32
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail_closure() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() {
-    || ->$0 Result<i32, String> {
-        let test = "test";
-        Ok(42i32)
-    };
-}
-"#,
-            r#"
-fn foo() {
-    || -> i32 {
-        let test = "test";
-        42i32
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail_only() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> { Ok(42i32) }
-"#,
-            r#"
-fn foo() -> i32 { 42i32 }
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail_block_like() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32>$0 {
-    if true {
-        Ok(42i32)
-    } else {
-        Ok(24i32)
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    if true {
-        42i32
-    } else {
-        24i32
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_without_block_closure() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> Result<i32, String>$0 {
-        if true {
-            Ok(42i32)
-        } else {
-            Ok(24i32)
-        }
-    };
-}
-"#,
-            r#"
-fn foo() {
-    || -> i32 {
-        if true {
-            42i32
-        } else {
-            24i32
-        }
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_nested_if() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32>$0 {
-    if true {
-        if false {
-            Ok(1)
-        } else {
-            Ok(2)
-        }
-    } else {
-        Ok(24i32)
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    if true {
-        if false {
-            1
-        } else {
-            2
-        }
-    } else {
-        24i32
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_await() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-async fn foo() -> Result<i$032> {
-    if true {
-        if false {
-            Ok(1.await)
-        } else {
-            Ok(2.await)
-        }
-    } else {
-        Ok(24i32.await)
-    }
-}
-"#,
-            r#"
-async fn foo() -> i32 {
-    if true {
-        if false {
-            1.await
-        } else {
-            2.await
-        }
-    } else {
-        24i32.await
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_array() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<[i32; 3]$0> { Ok([1, 2, 3]) }
-"#,
-            r#"
-fn foo() -> [i32; 3] { [1, 2, 3] }
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_cast() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -$0> Result<i32> {
-    if true {
-        if false {
-            Ok(1 as i32)
-        } else {
-            Ok(2 as i32)
-        }
-    } else {
-        Ok(24 as i32)
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    if true {
-        if false {
-            1 as i32
-        } else {
-            2 as i32
-        }
-    } else {
-        24 as i32
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail_block_like_match() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
-    let my_var = 5;
-    match my_var {
-        5 => Ok(42i32),
-        _ => Ok(24i32),
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let my_var = 5;
-    match my_var {
-        5 => 42i32,
-        _ => 24i32,
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_loop_with_tail() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
-    let my_var = 5;
-    loop {
-        println!("test");
-        5
-    }
-    Ok(my_var)
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let my_var = 5;
-    loop {
-        println!("test");
-        5
-    }
-    my_var
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_loop_in_let_stmt() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
-    let my_var = let x = loop {
-        break 1;
-    };
-    Ok(my_var)
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let my_var = let x = loop {
-        break 1;
-    };
-    my_var
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail_block_like_match_return_expr() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32>$0 {
-    let my_var = 5;
-    let res = match my_var {
-        5 => 42i32,
-        _ => return Ok(24i32),
-    };
-    Ok(res)
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let my_var = 5;
-    let res = match my_var {
-        5 => 42i32,
-        _ => return 24i32,
-    };
-    res
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
-    let my_var = 5;
-    let res = if my_var == 5 {
-        42i32
-    } else {
-        return Ok(24i32);
-    };
-    Ok(res)
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let my_var = 5;
-    let res = if my_var == 5 {
-        42i32
-    } else {
-        return 24i32;
-    };
-    res
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail_block_like_match_deeper() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
-    let my_var = 5;
-    match my_var {
-        5 => {
-            if true {
-                Ok(42i32)
-            } else {
-                Ok(25i32)
-            }
-        },
-        _ => {
-            let test = "test";
-            if test == "test" {
-                return Ok(bar());
-            }
-            Ok(53i32)
-        },
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let my_var = 5;
-    match my_var {
-        5 => {
-            if true {
-                42i32
-            } else {
-                25i32
-            }
-        },
-        _ => {
-            let test = "test";
-            if test == "test" {
-                return bar();
-            }
-            53i32
-        },
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_tail_block_like_early_return() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
-    let test = "test";
-    if test == "test" {
-        return Ok(24i32);
-    }
-    Ok(53i32)
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let test = "test";
-    if test == "test" {
-        return 24i32;
-    }
-    53i32
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_in_tail_position() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo(num: i32) -> $0Result<i32, String> {
-    return Ok(num)
-}
-"#,
-            r#"
-fn foo(num: i32) -> i32 {
-    return num
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_closure() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
-    let true_closure = || { return true; };
-    if the_field < 5 {
-        let mut i = 0;
-        if true_closure() {
-            return Ok(99);
-        } else {
-            return Ok(0);
-        }
-    }
-    Ok(the_field)
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> u32 {
-    let true_closure = || { return true; };
-    if the_field < 5 {
-        let mut i = 0;
-        if true_closure() {
-            return 99;
-        } else {
-            return 0;
-        }
-    }
-    the_field
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
-    let true_closure = || {
-        return true;
-    };
-    if the_field < 5 {
-        let mut i = 0;
-
-
-        if true_closure() {
-            return Ok(99);
-        } else {
-            return Ok(0);
-        }
-    }
-    let t = None;
-
-    Ok(t.unwrap_or_else(|| the_field))
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> u32 {
-    let true_closure = || {
-        return true;
-    };
-    if the_field < 5 {
-        let mut i = 0;
-
-
-        if true_closure() {
-            return 99;
-        } else {
-            return 0;
-        }
-    }
-    let t = None;
-
-    t.unwrap_or_else(|| the_field)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_simple_with_weird_forms() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0> {
-    let test = "test";
-    if test == "test" {
-        return Ok(24i32);
-    }
-    let mut i = 0;
-    loop {
-        if i == 1 {
-            break Ok(55);
-        }
-        i += 1;
-    }
-}
-"#,
-            r#"
-fn foo() -> i32 {
-    let test = "test";
-    if test == "test" {
-        return 24i32;
-    }
-    let mut i = 0;
-    loop {
-        if i == 1 {
-            break 55;
-        }
-        i += 1;
-    }
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
-    if the_field < 5 {
-        let mut i = 0;
-        loop {
-            if i > 5 {
-                return Ok(55u32);
-            }
-            i += 3;
-        }
-        match i {
-            5 => return Ok(99),
-            _ => return Ok(0),
-        };
-    }
-    Ok(the_field)
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> u32 {
-    if the_field < 5 {
-        let mut i = 0;
-        loop {
-            if i > 5 {
-                return 55u32;
-            }
-            i += 3;
-        }
-        match i {
-            5 => return 99,
-            _ => return 0,
-        };
-    }
-    the_field
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
-    if the_field < 5 {
-        let mut i = 0;
-        match i {
-            5 => return Ok(99),
-            _ => return Ok(0),
-        }
-    }
-    Ok(the_field)
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> u32 {
-    if the_field < 5 {
-        let mut i = 0;
-        match i {
-            5 => return 99,
-            _ => return 0,
-        }
-    }
-    the_field
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u32$0> {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return Ok(99)
-        } else {
-            return Ok(0)
-        }
-    }
-    Ok(the_field)
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> u32 {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return 99
-        } else {
-            return 0
-        }
-    }
-    the_field
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> Result<u3$02> {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return Ok(99);
-        } else {
-            return Ok(0);
-        }
-    }
-    Ok(the_field)
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> u32 {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return 99;
-        } else {
-            return 0;
-        }
-    }
-    the_field
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn unwrap_result_return_type_nested_type() {
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result, option
-fn foo() -> Result<Option<i32$0>, ()> {
-    Ok(Some(42))
-}
-"#,
-            r#"
-fn foo() -> Option<i32> {
-    Some(42)
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result, option
-fn foo() -> Result<Option<Result<i32$0, ()>>, ()> {
-    Ok(None)
-}
-"#,
-            r#"
-fn foo() -> Option<Result<i32, ()>> {
-    None
-}
-"#,
-        );
-
-        check_assist(
-            unwrap_result_return_type,
-            r#"
-//- minicore: result, option, iterators
-fn foo() -> Result<impl Iterator<Item = i32>$0, ()> {
-    Ok(Some(42).into_iter())
-}
-"#,
-            r#"
-fn foo() -> impl Iterator<Item = i32> {
-    Some(42).into_iter()
-}
-"#,
-        );
-    }
-}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs
new file mode 100644
index 00000000000..64d5e2c9b82
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs
@@ -0,0 +1,2229 @@
+use ide_db::{
+    famous_defs::FamousDefs,
+    syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
+};
+use itertools::Itertools;
+use syntax::{
+    ast::{self, Expr, HasGenericArgs},
+    match_ast, AstNode, NodeOrToken, SyntaxKind, TextRange,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: unwrap_option_return_type
+//
+// Unwrap the function's return type.
+//
+// ```
+// # //- minicore: option
+// fn foo() -> Option<i32>$0 { Some(42i32) }
+// ```
+// ->
+// ```
+// fn foo() -> i32 { 42i32 }
+// ```
+
+// Assist: unwrap_result_return_type
+//
+// Unwrap the function's return type.
+//
+// ```
+// # //- minicore: result
+// fn foo() -> Result<i32>$0 { Ok(42i32) }
+// ```
+// ->
+// ```
+// fn foo() -> i32 { 42i32 }
+// ```
+
+pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
+    let parent = ret_type.syntax().parent()?;
+    let body = match_ast! {
+        match parent {
+            ast::Fn(func) => func.body()?,
+            ast::ClosureExpr(closure) => match closure.body()? {
+                Expr::BlockExpr(block) => block,
+                // closures require a block when a return type is specified
+                _ => return None,
+            },
+            _ => return None,
+        }
+    };
+
+    let type_ref = &ret_type.ty()?;
+    let Some(hir::Adt::Enum(ret_enum)) = ctx.sema.resolve_type(type_ref)?.as_adt() else {
+        return None;
+    };
+
+    let famous_defs = FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate());
+
+    let kind = UnwrapperKind::ALL
+        .iter()
+        .find(|k| matches!(k.core_type(&famous_defs), Some(core_type) if ret_enum == core_type))?;
+
+    let happy_type = extract_wrapped_type(type_ref)?;
+
+    acc.add(kind.assist_id(), kind.label(), type_ref.syntax().text_range(), |builder| {
+        let body = ast::Expr::BlockExpr(body);
+
+        let mut exprs_to_unwrap = Vec::new();
+        let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_unwrap, e);
+        walk_expr(&body, &mut |expr| {
+            if let Expr::ReturnExpr(ret_expr) = expr {
+                if let Some(ret_expr_arg) = &ret_expr.expr() {
+                    for_each_tail_expr(ret_expr_arg, tail_cb);
+                }
+            }
+        });
+        for_each_tail_expr(&body, tail_cb);
+
+        let is_unit_type = is_unit_type(&happy_type);
+        if is_unit_type {
+            let mut text_range = ret_type.syntax().text_range();
+
+            if let Some(NodeOrToken::Token(token)) = ret_type.syntax().next_sibling_or_token() {
+                if token.kind() == SyntaxKind::WHITESPACE {
+                    text_range = TextRange::new(text_range.start(), token.text_range().end());
+                }
+            }
+
+            builder.delete(text_range);
+        } else {
+            builder.replace(type_ref.syntax().text_range(), happy_type.syntax().text());
+        }
+
+        for ret_expr_arg in exprs_to_unwrap {
+            let ret_expr_str = ret_expr_arg.to_string();
+
+            let needs_replacing = match kind {
+                UnwrapperKind::Option => ret_expr_str.starts_with("Some("),
+                UnwrapperKind::Result => {
+                    ret_expr_str.starts_with("Ok(") || ret_expr_str.starts_with("Err(")
+                }
+            };
+
+            if needs_replacing {
+                let arg_list = ret_expr_arg.syntax().children().find_map(ast::ArgList::cast);
+                if let Some(arg_list) = arg_list {
+                    if is_unit_type {
+                        match ret_expr_arg.syntax().prev_sibling_or_token() {
+                            // Useful to delete the entire line without leaving trailing whitespaces
+                            Some(whitespace) => {
+                                let new_range = TextRange::new(
+                                    whitespace.text_range().start(),
+                                    ret_expr_arg.syntax().text_range().end(),
+                                );
+                                builder.delete(new_range);
+                            }
+                            None => {
+                                builder.delete(ret_expr_arg.syntax().text_range());
+                            }
+                        }
+                    } else {
+                        builder.replace(
+                            ret_expr_arg.syntax().text_range(),
+                            arg_list.args().join(", "),
+                        );
+                    }
+                }
+            } else if matches!(kind, UnwrapperKind::Option if ret_expr_str == "None") {
+                builder.replace(ret_expr_arg.syntax().text_range(), "()");
+            }
+        }
+    })
+}
+
+enum UnwrapperKind {
+    Option,
+    Result,
+}
+
+impl UnwrapperKind {
+    const ALL: &'static [UnwrapperKind] = &[UnwrapperKind::Option, UnwrapperKind::Result];
+
+    fn assist_id(&self) -> AssistId {
+        let s = match self {
+            UnwrapperKind::Option => "unwrap_option_return_type",
+            UnwrapperKind::Result => "unwrap_result_return_type",
+        };
+
+        AssistId(s, AssistKind::RefactorRewrite)
+    }
+
+    fn label(&self) -> &'static str {
+        match self {
+            UnwrapperKind::Option => "Unwrap Option return type",
+            UnwrapperKind::Result => "Unwrap Result return type",
+        }
+    }
+
+    fn core_type(&self, famous_defs: &FamousDefs<'_, '_>) -> Option<hir::Enum> {
+        match self {
+            UnwrapperKind::Option => famous_defs.core_option_Option(),
+            UnwrapperKind::Result => famous_defs.core_result_Result(),
+        }
+    }
+}
+
+fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
+    match e {
+        Expr::BreakExpr(break_expr) => {
+            if let Some(break_expr_arg) = break_expr.expr() {
+                for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
+            }
+        }
+        Expr::ReturnExpr(_) => {
+            // all return expressions have already been handled by the walk loop
+        }
+        e => acc.push(e.clone()),
+    }
+}
+
+// Tries to extract `T` from `Option<T>` or `Result<T, E>`.
+fn extract_wrapped_type(ty: &ast::Type) -> Option<ast::Type> {
+    let ast::Type::PathType(path_ty) = ty else {
+        return None;
+    };
+    let path = path_ty.path()?;
+    let segment = path.first_segment()?;
+    let generic_arg_list = segment.generic_arg_list()?;
+    let generic_args: Vec<_> = generic_arg_list.generic_args().collect();
+    let ast::GenericArg::TypeArg(happy_type) = generic_args.first()? else {
+        return None;
+    };
+    happy_type.ty()
+}
+
+fn is_unit_type(ty: &ast::Type) -> bool {
+    let ast::Type::TupleType(tuple) = ty else { return false };
+    tuple.fields().next().is_none()
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::{check_assist_by_label, check_assist_not_applicable_by_label};
+
+    use super::*;
+
+    #[test]
+    fn unwrap_option_return_type_simple() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+    let test = "test";
+    return Some(42i32);
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_unit_type() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<()$0> {
+    Some(())
+}
+"#,
+            r#"
+fn foo() {
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        // Unformatted return type
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<()$0>{
+    Some(())
+}
+"#,
+            r#"
+fn foo() {
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_none() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+    if true {
+        Some(42)
+    } else {
+        None
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        42
+    } else {
+        ()
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_ending_with_parent() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+    if true {
+        Some(42)
+    } else {
+        foo()
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        42
+    } else {
+        foo()
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_break_split_tail() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i3$02> {
+    loop {
+        break if true {
+            Some(1)
+        } else {
+            Some(0)
+        };
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    loop {
+        break if true {
+            1
+        } else {
+            0
+        };
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> Option<i32$0> {
+        let test = "test";
+        return Some(42i32);
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> i32 {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_return_type_bad_cursor() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32 {
+    let test = "test";$0
+    return 42i32;
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_return_type_bad_cursor_closure() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> i32 {
+        let test = "test";$0
+        return 42i32;
+    };
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_closure_non_block() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() { || -> i$032 3; }
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_return_type_already_not_option_std() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_return_type_already_not_option_closure() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> i32$0 {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() ->$0 Option<i32> {
+    let test = "test";
+    Some(42i32)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    42i32
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || ->$0 Option<i32> {
+        let test = "test";
+        Some(42i32)
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> i32 {
+        let test = "test";
+        42i32
+    };
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail_only() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> { Some(42i32) }
+"#,
+            r#"
+fn foo() -> i32 { 42i32 }
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail_block_like() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32>$0 {
+    if true {
+        Some(42i32)
+    } else {
+        Some(24i32)
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        42i32
+    } else {
+        24i32
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_without_block_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> Option<i32>$0 {
+        if true {
+            Some(42i32)
+        } else {
+            Some(24i32)
+        }
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> i32 {
+        if true {
+            42i32
+        } else {
+            24i32
+        }
+    };
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_nested_if() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32>$0 {
+    if true {
+        if false {
+            Some(1)
+        } else {
+            Some(2)
+        }
+    } else {
+        Some(24i32)
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        if false {
+            1
+        } else {
+            2
+        }
+    } else {
+        24i32
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_await() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+async fn foo() -> Option<i$032> {
+    if true {
+        if false {
+            Some(1.await)
+        } else {
+            Some(2.await)
+        }
+    } else {
+        Some(24i32.await)
+    }
+}
+"#,
+            r#"
+async fn foo() -> i32 {
+    if true {
+        if false {
+            1.await
+        } else {
+            2.await
+        }
+    } else {
+        24i32.await
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_array() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<[i32; 3]$0> { Some([1, 2, 3]) }
+"#,
+            r#"
+fn foo() -> [i32; 3] { [1, 2, 3] }
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_cast() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -$0> Option<i32> {
+    if true {
+        if false {
+            Some(1 as i32)
+        } else {
+            Some(2 as i32)
+        }
+    } else {
+        Some(24 as i32)
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        if false {
+            1 as i32
+        } else {
+            2 as i32
+        }
+    } else {
+        24 as i32
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail_block_like_match() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let my_var = 5;
+    match my_var {
+        5 => Some(42i32),
+        _ => Some(24i32),
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    match my_var {
+        5 => 42i32,
+        _ => 24i32,
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_loop_with_tail() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    Some(my_var)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    my_var
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_loop_in_let_stmt() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let my_var = let x = loop {
+        break 1;
+    };
+    Some(my_var)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = let x = loop {
+        break 1;
+    };
+    my_var
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail_block_like_match_return_expr() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32>$0 {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return Some(24i32),
+    };
+    Some(res)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return 24i32,
+    };
+    res
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return Some(24i32);
+    };
+    Some(res)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return 24i32;
+    };
+    res
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail_block_like_match_deeper() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                Some(42i32)
+            } else {
+                Some(25i32)
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return Some(bar());
+            }
+            Some(53i32)
+        },
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                42i32
+            } else {
+                25i32
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return bar();
+            }
+            53i32
+        },
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_tail_block_like_early_return() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let test = "test";
+    if test == "test" {
+        return Some(24i32);
+    }
+    Some(53i32)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    53i32
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_in_tail_position() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo(num: i32) -> $0Option<i32> {
+    return Some(num)
+}
+"#,
+            r#"
+fn foo(num: i32) -> i32 {
+    return num
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return Some(99);
+        } else {
+            return Some(0);
+        }
+    }
+    Some(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return Some(99);
+        } else {
+            return Some(0);
+        }
+    }
+    let t = None;
+
+    Some(t.unwrap_or_else(|| the_field))
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    let t = None;
+
+    t.unwrap_or_else(|| the_field)
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_simple_with_weird_forms() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let test = "test";
+    if test == "test" {
+        return Some(24i32);
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break Some(55);
+        }
+        i += 1;
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break 55;
+        }
+        i += 1;
+    }
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return Some(55u32);
+            }
+            i += 3;
+        }
+        match i {
+            5 => return Some(99),
+            _ => return Some(0),
+        };
+    }
+    Some(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return 55u32;
+            }
+            i += 3;
+        }
+        match i {
+            5 => return 99,
+            _ => return 0,
+        };
+    }
+    the_field
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return Some(99),
+            _ => return Some(0),
+        }
+    }
+    Some(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return 99,
+            _ => return 0,
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u32$0> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Some(99)
+        } else {
+            return Some(0)
+        }
+    }
+    Some(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99
+        } else {
+            return 0
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> Option<u3$02> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Some(99);
+        } else {
+            return Some(0);
+        }
+    }
+    Some(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_option_return_type_nested_type() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option, result
+fn foo() -> Option<Result<i32$0, ()>> {
+    Some(Ok(42))
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ()> {
+    Ok(42)
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option, result
+fn foo() -> Option<Result<Option<i32$0>, ()>> {
+    Some(Err())
+}
+"#,
+            r#"
+fn foo() -> Result<Option<i32>, ()> {
+    Err()
+}
+"#,
+            "Unwrap Option return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: option, result, iterators
+fn foo() -> Option<impl Iterator<Item = i32>$0> {
+    Some(Some(42).into_iter())
+}
+"#,
+            r#"
+fn foo() -> impl Iterator<Item = i32> {
+    Some(42).into_iter()
+}
+"#,
+            "Unwrap Option return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i3$02> {
+    let test = "test";
+    return Ok(42i32);
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_unit_type() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<(), Box<dyn Error$0>> {
+    Ok(())
+}
+"#,
+            r#"
+fn foo() {
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        // Unformatted return type
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<(), Box<dyn Error$0>>{
+    Ok(())
+}
+"#,
+            r#"
+fn foo() {
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_ending_with_parent() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32, Box<dyn Error$0>> {
+    if true {
+        Ok(42)
+    } else {
+        foo()
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        42
+    } else {
+        foo()
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_break_split_tail() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i3$02, String> {
+    loop {
+        break if true {
+            Ok(1)
+        } else {
+            Ok(0)
+        };
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    loop {
+        break if true {
+            1
+        } else {
+            0
+        };
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> Result<i32$0> {
+        let test = "test";
+        return Ok(42i32);
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> i32 {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_return_type_bad_cursor() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32 {
+    let test = "test";$0
+    return 42i32;
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_return_type_bad_cursor_closure() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> i32 {
+        let test = "test";$0
+        return 42i32;
+    };
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_closure_non_block() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() { || -> i$032 3; }
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_return_type_already_not_result_std() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_return_type_already_not_result_closure() {
+        check_assist_not_applicable_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> i32$0 {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() ->$0 Result<i32> {
+    let test = "test";
+    Ok(42i32)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    42i32
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || ->$0 Result<i32, String> {
+        let test = "test";
+        Ok(42i32)
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> i32 {
+        let test = "test";
+        42i32
+    };
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail_only() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> { Ok(42i32) }
+"#,
+            r#"
+fn foo() -> i32 { 42i32 }
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail_block_like() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32>$0 {
+    if true {
+        Ok(42i32)
+    } else {
+        Ok(24i32)
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        42i32
+    } else {
+        24i32
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_without_block_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> Result<i32, String>$0 {
+        if true {
+            Ok(42i32)
+        } else {
+            Ok(24i32)
+        }
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> i32 {
+        if true {
+            42i32
+        } else {
+            24i32
+        }
+    };
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_nested_if() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32>$0 {
+    if true {
+        if false {
+            Ok(1)
+        } else {
+            Ok(2)
+        }
+    } else {
+        Ok(24i32)
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        if false {
+            1
+        } else {
+            2
+        }
+    } else {
+        24i32
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_await() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+async fn foo() -> Result<i$032> {
+    if true {
+        if false {
+            Ok(1.await)
+        } else {
+            Ok(2.await)
+        }
+    } else {
+        Ok(24i32.await)
+    }
+}
+"#,
+            r#"
+async fn foo() -> i32 {
+    if true {
+        if false {
+            1.await
+        } else {
+            2.await
+        }
+    } else {
+        24i32.await
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_array() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<[i32; 3]$0> { Ok([1, 2, 3]) }
+"#,
+            r#"
+fn foo() -> [i32; 3] { [1, 2, 3] }
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_cast() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -$0> Result<i32> {
+    if true {
+        if false {
+            Ok(1 as i32)
+        } else {
+            Ok(2 as i32)
+        }
+    } else {
+        Ok(24 as i32)
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    if true {
+        if false {
+            1 as i32
+        } else {
+            2 as i32
+        }
+    } else {
+        24 as i32
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail_block_like_match() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+    let my_var = 5;
+    match my_var {
+        5 => Ok(42i32),
+        _ => Ok(24i32),
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    match my_var {
+        5 => 42i32,
+        _ => 24i32,
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_loop_with_tail() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    Ok(my_var)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    my_var
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_loop_in_let_stmt() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+    let my_var = let x = loop {
+        break 1;
+    };
+    Ok(my_var)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = let x = loop {
+        break 1;
+    };
+    my_var
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail_block_like_match_return_expr() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32>$0 {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return Ok(24i32),
+    };
+    Ok(res)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return 24i32,
+    };
+    res
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return Ok(24i32);
+    };
+    Ok(res)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return 24i32;
+    };
+    res
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail_block_like_match_deeper() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                Ok(42i32)
+            } else {
+                Ok(25i32)
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return Ok(bar());
+            }
+            Ok(53i32)
+        },
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                42i32
+            } else {
+                25i32
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return bar();
+            }
+            53i32
+        },
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_tail_block_like_early_return() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+    let test = "test";
+    if test == "test" {
+        return Ok(24i32);
+    }
+    Ok(53i32)
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    53i32
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_in_tail_position() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo(num: i32) -> $0Result<i32, String> {
+    return Ok(num)
+}
+"#,
+            r#"
+fn foo(num: i32) -> i32 {
+    return num
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_closure() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return Ok(99);
+        } else {
+            return Ok(0);
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return Ok(99);
+        } else {
+            return Ok(0);
+        }
+    }
+    let t = None;
+
+    Ok(t.unwrap_or_else(|| the_field))
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    let t = None;
+
+    t.unwrap_or_else(|| the_field)
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_simple_with_weird_forms() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0> {
+    let test = "test";
+    if test == "test" {
+        return Ok(24i32);
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break Ok(55);
+        }
+        i += 1;
+    }
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break 55;
+        }
+        i += 1;
+    }
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return Ok(55u32);
+            }
+            i += 3;
+        }
+        match i {
+            5 => return Ok(99),
+            _ => return Ok(0),
+        };
+    }
+    Ok(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return 55u32;
+            }
+            i += 3;
+        }
+        match i {
+            5 => return 99,
+            _ => return 0,
+        };
+    }
+    the_field
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return Ok(99),
+            _ => return Ok(0),
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return 99,
+            _ => return 0,
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u32$0> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Ok(99)
+        } else {
+            return Ok(0)
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99
+        } else {
+            return 0
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> Result<u3$02> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Ok(99);
+        } else {
+            return Ok(0);
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+
+    #[test]
+    fn unwrap_result_return_type_nested_type() {
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result, option
+fn foo() -> Result<Option<i32$0>, ()> {
+    Ok(Some(42))
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    Some(42)
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result, option
+fn foo() -> Result<Option<Result<i32$0, ()>>, ()> {
+    Ok(None)
+}
+"#,
+            r#"
+fn foo() -> Option<Result<i32, ()>> {
+    None
+}
+"#,
+            "Unwrap Result return type",
+        );
+
+        check_assist_by_label(
+            unwrap_return_type,
+            r#"
+//- minicore: result, option, iterators
+fn foo() -> Result<impl Iterator<Item = i32>$0, ()> {
+    Ok(Some(42).into_iter())
+}
+"#,
+            r#"
+fn foo() -> impl Iterator<Item = i32> {
+    Some(42).into_iter()
+}
+"#,
+            "Unwrap Result return type",
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
new file mode 100644
index 00000000000..2d918a5b1c1
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
@@ -0,0 +1,2457 @@
+use std::iter;
+
+use hir::HasSource;
+use ide_db::{
+    assists::GroupLabel,
+    famous_defs::FamousDefs,
+    syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
+};
+use itertools::Itertools;
+use syntax::{
+    ast::{self, make, Expr, HasGenericParams},
+    match_ast, ted, AstNode, ToSmolStr,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: wrap_return_type_in_option
+//
+// Wrap the function's return type into Option.
+//
+// ```
+// # //- minicore: option
+// fn foo() -> i32$0 { 42i32 }
+// ```
+// ->
+// ```
+// fn foo() -> Option<i32> { Some(42i32) }
+// ```
+
+// Assist: wrap_return_type_in_result
+//
+// Wrap the function's return type into Result.
+//
+// ```
+// # //- minicore: result
+// fn foo() -> i32$0 { 42i32 }
+// ```
+// ->
+// ```
+// fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
+// ```
+
+pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
+    let parent = ret_type.syntax().parent()?;
+    let body = match_ast! {
+        match parent {
+            ast::Fn(func) => func.body()?,
+            ast::ClosureExpr(closure) => match closure.body()? {
+                Expr::BlockExpr(block) => block,
+                // closures require a block when a return type is specified
+                _ => return None,
+            },
+            _ => return None,
+        }
+    };
+
+    let type_ref = &ret_type.ty()?;
+    let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
+    let famous_defs = FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate());
+
+    for kind in WrapperKind::ALL {
+        let Some(core_wrapper) = kind.core_type(&famous_defs) else {
+            continue;
+        };
+
+        if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == core_wrapper) {
+            // The return type is already wrapped
+            cov_mark::hit!(wrap_return_type_simple_return_type_already_wrapped);
+            continue;
+        }
+
+        acc.add_group(
+            &GroupLabel("Wrap return type in...".into()),
+            kind.assist_id(),
+            kind.label(),
+            type_ref.syntax().text_range(),
+            |edit| {
+                let alias = wrapper_alias(ctx, &core_wrapper, type_ref, kind.symbol());
+                let new_return_ty =
+                    alias.unwrap_or_else(|| kind.wrap_type(type_ref)).clone_for_update();
+
+                let body = edit.make_mut(ast::Expr::BlockExpr(body.clone()));
+
+                let mut exprs_to_wrap = Vec::new();
+                let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e);
+                walk_expr(&body, &mut |expr| {
+                    if let Expr::ReturnExpr(ret_expr) = expr {
+                        if let Some(ret_expr_arg) = &ret_expr.expr() {
+                            for_each_tail_expr(ret_expr_arg, tail_cb);
+                        }
+                    }
+                });
+                for_each_tail_expr(&body, tail_cb);
+
+                for ret_expr_arg in exprs_to_wrap {
+                    let happy_wrapped = make::expr_call(
+                        make::expr_path(make::ext::ident_path(kind.happy_ident())),
+                        make::arg_list(iter::once(ret_expr_arg.clone())),
+                    )
+                    .clone_for_update();
+                    ted::replace(ret_expr_arg.syntax(), happy_wrapped.syntax());
+                }
+
+                let old_return_ty = edit.make_mut(type_ref.clone());
+                ted::replace(old_return_ty.syntax(), new_return_ty.syntax());
+
+                if let WrapperKind::Result = kind {
+                    // Add a placeholder snippet at the first generic argument that doesn't equal the return type.
+                    // This is normally the error type, but that may not be the case when we inserted a type alias.
+                    let args =
+                        new_return_ty.syntax().descendants().find_map(ast::GenericArgList::cast);
+                    let error_type_arg = args.and_then(|list| {
+                        list.generic_args().find(|arg| match arg {
+                            ast::GenericArg::TypeArg(_) => {
+                                arg.syntax().text() != type_ref.syntax().text()
+                            }
+                            ast::GenericArg::LifetimeArg(_) => false,
+                            _ => true,
+                        })
+                    });
+                    if let Some(error_type_arg) = error_type_arg {
+                        if let Some(cap) = ctx.config.snippet_cap {
+                            edit.add_placeholder_snippet(cap, error_type_arg);
+                        }
+                    }
+                }
+            },
+        );
+    }
+
+    Some(())
+}
+
+enum WrapperKind {
+    Option,
+    Result,
+}
+
+impl WrapperKind {
+    const ALL: &'static [WrapperKind] = &[WrapperKind::Option, WrapperKind::Result];
+
+    fn assist_id(&self) -> AssistId {
+        let s = match self {
+            WrapperKind::Option => "wrap_return_type_in_option",
+            WrapperKind::Result => "wrap_return_type_in_result",
+        };
+
+        AssistId(s, AssistKind::RefactorRewrite)
+    }
+
+    fn label(&self) -> &'static str {
+        match self {
+            WrapperKind::Option => "Wrap return type in Option",
+            WrapperKind::Result => "Wrap return type in Result",
+        }
+    }
+
+    fn happy_ident(&self) -> &'static str {
+        match self {
+            WrapperKind::Option => "Some",
+            WrapperKind::Result => "Ok",
+        }
+    }
+
+    fn core_type(&self, famous_defs: &FamousDefs<'_, '_>) -> Option<hir::Enum> {
+        match self {
+            WrapperKind::Option => famous_defs.core_option_Option(),
+            WrapperKind::Result => famous_defs.core_result_Result(),
+        }
+    }
+
+    fn symbol(&self) -> hir::Symbol {
+        match self {
+            WrapperKind::Option => hir::sym::Option.clone(),
+            WrapperKind::Result => hir::sym::Result.clone(),
+        }
+    }
+
+    fn wrap_type(&self, type_ref: &ast::Type) -> ast::Type {
+        match self {
+            WrapperKind::Option => make::ext::ty_option(type_ref.clone()),
+            WrapperKind::Result => make::ext::ty_result(type_ref.clone(), make::ty_placeholder()),
+        }
+    }
+}
+
+// Try to find an wrapper type alias in the current scope (shadowing the default).
+fn wrapper_alias(
+    ctx: &AssistContext<'_>,
+    core_wrapper: &hir::Enum,
+    ret_type: &ast::Type,
+    wrapper: hir::Symbol,
+) -> Option<ast::Type> {
+    let wrapper_path = hir::ModPath::from_segments(
+        hir::PathKind::Plain,
+        iter::once(hir::Name::new_symbol_root(wrapper)),
+    );
+
+    ctx.sema.resolve_mod_path(ret_type.syntax(), &wrapper_path).and_then(|def| {
+        def.filter_map(|def| match def.as_module_def()? {
+            hir::ModuleDef::TypeAlias(alias) => {
+                let enum_ty = alias.ty(ctx.db()).as_adt()?.as_enum()?;
+                (&enum_ty == core_wrapper).then_some(alias)
+            }
+            _ => None,
+        })
+        .find_map(|alias| {
+            let mut inserted_ret_type = false;
+            let generic_params = alias
+                .source(ctx.db())?
+                .value
+                .generic_param_list()?
+                .generic_params()
+                .map(|param| match param {
+                    // Replace the very first type parameter with the functions return type.
+                    ast::GenericParam::TypeParam(_) if !inserted_ret_type => {
+                        inserted_ret_type = true;
+                        ret_type.to_smolstr()
+                    }
+                    ast::GenericParam::LifetimeParam(_) => make::lifetime("'_").to_smolstr(),
+                    _ => make::ty_placeholder().to_smolstr(),
+                })
+                .join(", ");
+
+            let name = alias.name(ctx.db());
+            let name = name.as_str();
+            Some(make::ty(&format!("{name}<{generic_params}>")))
+        })
+    })
+}
+
+fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
+    match e {
+        Expr::BreakExpr(break_expr) => {
+            if let Some(break_expr_arg) = break_expr.expr() {
+                for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
+            }
+        }
+        Expr::ReturnExpr(_) => {
+            // all return expressions have already been handled by the walk loop
+        }
+        e => acc.push(e.clone()),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::{check_assist_by_label, check_assist_not_applicable_by_label};
+
+    use super::*;
+
+    #[test]
+    fn wrap_return_type_in_option_simple() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i3$02 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let test = "test";
+    return Some(42i32);
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_break_split_tail() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i3$02 {
+    loop {
+        break if true {
+            1
+        } else {
+            0
+        };
+    }
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    loop {
+        break if true {
+            Some(1)
+        } else {
+            Some(0)
+        };
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> i32$0 {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> Option<i32> {
+        let test = "test";
+        return Some(42i32);
+    };
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_return_type_bad_cursor() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32 {
+    let test = "test";$0
+    return 42i32;
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_return_type_bad_cursor_closure() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> i32 {
+        let test = "test";$0
+        return 42i32;
+    };
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_closure_non_block() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() { || -> i$032 3; }
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_return_type_already_option_std() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> core::option::Option<i32$0> {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_return_type_already_option() {
+        cov_mark::check!(wrap_return_type_simple_return_type_already_wrapped);
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> Option<i32$0> {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_return_type_already_option_closure() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> Option<i32$0, String> {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_cursor() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> $0i32 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let test = "test";
+    return Some(42i32);
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() ->$0 i32 {
+    let test = "test";
+    42i32
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let test = "test";
+    Some(42i32)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || ->$0 i32 {
+        let test = "test";
+        42i32
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> Option<i32> {
+        let test = "test";
+        Some(42i32)
+    };
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail_only() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 { 42i32 }
+"#,
+            r#"
+fn foo() -> Option<i32> { Some(42i32) }
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail_block_like() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    if true {
+        42i32
+    } else {
+        24i32
+    }
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    if true {
+        Some(42i32)
+    } else {
+        Some(24i32)
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_without_block_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() {
+    || -> i32$0 {
+        if true {
+            42i32
+        } else {
+            24i32
+        }
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> Option<i32> {
+        if true {
+            Some(42i32)
+        } else {
+            Some(24i32)
+        }
+    };
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_nested_if() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    if true {
+        if false {
+            1
+        } else {
+            2
+        }
+    } else {
+        24i32
+    }
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    if true {
+        if false {
+            Some(1)
+        } else {
+            Some(2)
+        }
+    } else {
+        Some(24i32)
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_await() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+async fn foo() -> i$032 {
+    if true {
+        if false {
+            1.await
+        } else {
+            2.await
+        }
+    } else {
+        24i32.await
+    }
+}
+"#,
+            r#"
+async fn foo() -> Option<i32> {
+    if true {
+        if false {
+            Some(1.await)
+        } else {
+            Some(2.await)
+        }
+    } else {
+        Some(24i32.await)
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_array() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> [i32;$0 3] { [1, 2, 3] }
+"#,
+            r#"
+fn foo() -> Option<[i32; 3]> { Some([1, 2, 3]) }
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_cast() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -$0> i32 {
+    if true {
+        if false {
+            1 as i32
+        } else {
+            2 as i32
+        }
+    } else {
+        24 as i32
+    }
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    if true {
+        if false {
+            Some(1 as i32)
+        } else {
+            Some(2 as i32)
+        }
+    } else {
+        Some(24 as i32)
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail_block_like_match() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let my_var = 5;
+    match my_var {
+        5 => 42i32,
+        _ => 24i32,
+    }
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let my_var = 5;
+    match my_var {
+        5 => Some(42i32),
+        _ => Some(24i32),
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_loop_with_tail() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    my_var
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    Some(my_var)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_loop_in_let_stmt() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let my_var = let x = loop {
+        break 1;
+    };
+    my_var
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let my_var = let x = loop {
+        break 1;
+    };
+    Some(my_var)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail_block_like_match_return_expr() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return 24i32,
+    };
+    res
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return Some(24i32),
+    };
+    Some(res)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return 24i32;
+    };
+    res
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return Some(24i32);
+    };
+    Some(res)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail_block_like_match_deeper() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                42i32
+            } else {
+                25i32
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return bar();
+            }
+            53i32
+        },
+    }
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                Some(42i32)
+            } else {
+                Some(25i32)
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return Some(bar());
+            }
+            Some(53i32)
+        },
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_tail_block_like_early_return() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i$032 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    53i32
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let test = "test";
+    if test == "test" {
+        return Some(24i32);
+    }
+    Some(53i32)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_in_option_tail_position() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo(num: i32) -> $0i32 {
+    return num
+}
+"#,
+            r#"
+fn foo(num: i32) -> Option<i32> {
+    return Some(num)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) ->$0 u32 {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Option<u32> {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return Some(99);
+        } else {
+            return Some(0);
+        }
+    }
+    Some(the_field)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> u32$0 {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    let t = None;
+
+    t.unwrap_or_else(|| the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Option<u32> {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return Some(99);
+        } else {
+            return Some(0);
+        }
+    }
+    let t = None;
+
+    Some(t.unwrap_or_else(|| the_field))
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_option_simple_with_weird_forms() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break 55;
+        }
+        i += 1;
+    }
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    let test = "test";
+    if test == "test" {
+        return Some(24i32);
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break Some(55);
+        }
+        i += 1;
+    }
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> u32$0 {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return 55u32;
+            }
+            i += 3;
+        }
+        match i {
+            5 => return 99,
+            _ => return 0,
+        };
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Option<u32> {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return Some(55u32);
+            }
+            i += 3;
+        }
+        match i {
+            5 => return Some(99),
+            _ => return Some(0),
+        };
+    }
+    Some(the_field)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> u3$02 {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return 99,
+            _ => return 0,
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Option<u32> {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return Some(99),
+            _ => return Some(0),
+        }
+    }
+    Some(the_field)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> u32$0 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99
+        } else {
+            return 0
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Option<u32> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Some(99)
+        } else {
+            return Some(0)
+        }
+    }
+    Some(the_field)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo(the_field: u32) -> $0u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Option<u32> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Some(99);
+        } else {
+            return Some(0);
+        }
+    }
+    Some(the_field)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_local_option_type() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+type Option<T> = core::option::Option<T>;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+type Option<T> = core::option::Option<T>;
+
+fn foo() -> Option<i32> {
+    return Some(42i32);
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+type Option2<T> = core::option::Option<T>;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+type Option2<T> = core::option::Option<T>;
+
+fn foo() -> Option<i32> {
+    return Some(42i32);
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_imported_local_option_type() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+mod some_module {
+    pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::Option;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+mod some_module {
+    pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::Option;
+
+fn foo() -> Option<i32> {
+    return Some(42i32);
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+mod some_module {
+    pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::*;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+mod some_module {
+    pub type Option<T> = core::option::Option<T>;
+}
+
+use some_module::*;
+
+fn foo() -> Option<i32> {
+    return Some(42i32);
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_local_option_type_from_function_body() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i3$02 {
+    type Option<T> = core::option::Option<T>;
+    0
+}
+"#,
+            r#"
+fn foo() -> Option<i32> {
+    type Option<T> = core::option::Option<T>;
+    Some(0)
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_local_option_type_already_using_alias() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+pub type Option<T> = core::option::Option<T>;
+
+fn foo() -> Option<i3$02> {
+    return Some(42i32);
+}
+"#,
+            WrapperKind::Option.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i3$02 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let test = "test";
+    return Ok(42i32);
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_break_split_tail() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i3$02 {
+    loop {
+        break if true {
+            1
+        } else {
+            0
+        };
+    }
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    loop {
+        break if true {
+            Ok(1)
+        } else {
+            Ok(0)
+        };
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> i32$0 {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> Result<i32, ${0:_}> {
+        let test = "test";
+        return Ok(42i32);
+    };
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_return_type_bad_cursor() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32 {
+    let test = "test";$0
+    return 42i32;
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_return_type_bad_cursor_closure() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> i32 {
+        let test = "test";$0
+        return 42i32;
+    };
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_closure_non_block() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() { || -> i$032 3; }
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_return_type_already_result_std() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> core::result::Result<i32$0, String> {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_return_type_already_result() {
+        cov_mark::check!(wrap_return_type_simple_return_type_already_wrapped);
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> Result<i32$0, String> {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_return_type_already_result_closure() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> Result<i32$0, String> {
+        let test = "test";
+        return 42i32;
+    };
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_cursor() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> $0i32 {
+    let test = "test";
+    return 42i32;
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let test = "test";
+    return Ok(42i32);
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() ->$0 i32 {
+    let test = "test";
+    42i32
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let test = "test";
+    Ok(42i32)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || ->$0 i32 {
+        let test = "test";
+        42i32
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> Result<i32, ${0:_}> {
+        let test = "test";
+        Ok(42i32)
+    };
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail_only() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 { 42i32 }
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail_block_like() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    if true {
+        42i32
+    } else {
+        24i32
+    }
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    if true {
+        Ok(42i32)
+    } else {
+        Ok(24i32)
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_without_block_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() {
+    || -> i32$0 {
+        if true {
+            42i32
+        } else {
+            24i32
+        }
+    };
+}
+"#,
+            r#"
+fn foo() {
+    || -> Result<i32, ${0:_}> {
+        if true {
+            Ok(42i32)
+        } else {
+            Ok(24i32)
+        }
+    };
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_nested_if() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    if true {
+        if false {
+            1
+        } else {
+            2
+        }
+    } else {
+        24i32
+    }
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    if true {
+        if false {
+            Ok(1)
+        } else {
+            Ok(2)
+        }
+    } else {
+        Ok(24i32)
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_await() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+async fn foo() -> i$032 {
+    if true {
+        if false {
+            1.await
+        } else {
+            2.await
+        }
+    } else {
+        24i32.await
+    }
+}
+"#,
+            r#"
+async fn foo() -> Result<i32, ${0:_}> {
+    if true {
+        if false {
+            Ok(1.await)
+        } else {
+            Ok(2.await)
+        }
+    } else {
+        Ok(24i32.await)
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_array() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> [i32;$0 3] { [1, 2, 3] }
+"#,
+            r#"
+fn foo() -> Result<[i32; 3], ${0:_}> { Ok([1, 2, 3]) }
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_cast() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -$0> i32 {
+    if true {
+        if false {
+            1 as i32
+        } else {
+            2 as i32
+        }
+    } else {
+        24 as i32
+    }
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    if true {
+        if false {
+            Ok(1 as i32)
+        } else {
+            Ok(2 as i32)
+        }
+    } else {
+        Ok(24 as i32)
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail_block_like_match() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let my_var = 5;
+    match my_var {
+        5 => 42i32,
+        _ => 24i32,
+    }
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let my_var = 5;
+    match my_var {
+        5 => Ok(42i32),
+        _ => Ok(24i32),
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_loop_with_tail() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    my_var
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let my_var = 5;
+    loop {
+        println!("test");
+        5
+    }
+    Ok(my_var)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_loop_in_let_stmt() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let my_var = let x = loop {
+        break 1;
+    };
+    my_var
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let my_var = let x = loop {
+        break 1;
+    };
+    Ok(my_var)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail_block_like_match_return_expr() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return 24i32,
+    };
+    res
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let my_var = 5;
+    let res = match my_var {
+        5 => 42i32,
+        _ => return Ok(24i32),
+    };
+    Ok(res)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return 24i32;
+    };
+    res
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let my_var = 5;
+    let res = if my_var == 5 {
+        42i32
+    } else {
+        return Ok(24i32);
+    };
+    Ok(res)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail_block_like_match_deeper() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                42i32
+            } else {
+                25i32
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return bar();
+            }
+            53i32
+        },
+    }
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let my_var = 5;
+    match my_var {
+        5 => {
+            if true {
+                Ok(42i32)
+            } else {
+                Ok(25i32)
+            }
+        },
+        _ => {
+            let test = "test";
+            if test == "test" {
+                return Ok(bar());
+            }
+            Ok(53i32)
+        },
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_tail_block_like_early_return() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i$032 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    53i32
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let test = "test";
+    if test == "test" {
+        return Ok(24i32);
+    }
+    Ok(53i32)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_in_result_tail_position() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo(num: i32) -> $0i32 {
+    return num
+}
+"#,
+            r#"
+fn foo(num: i32) -> Result<i32, ${0:_}> {
+    return Ok(num)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_closure() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) ->$0 u32 {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+    let true_closure = || { return true; };
+    if the_field < 5 {
+        let mut i = 0;
+        if true_closure() {
+            return Ok(99);
+        } else {
+            return Ok(0);
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> u32$0 {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    let t = None;
+
+    t.unwrap_or_else(|| the_field)
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+    let true_closure = || {
+        return true;
+    };
+    if the_field < 5 {
+        let mut i = 0;
+
+
+        if true_closure() {
+            return Ok(99);
+        } else {
+            return Ok(0);
+        }
+    }
+    let t = None;
+
+    Ok(t.unwrap_or_else(|| the_field))
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_result_simple_with_weird_forms() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    let test = "test";
+    if test == "test" {
+        return 24i32;
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break 55;
+        }
+        i += 1;
+    }
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    let test = "test";
+    if test == "test" {
+        return Ok(24i32);
+    }
+    let mut i = 0;
+    loop {
+        if i == 1 {
+            break Ok(55);
+        }
+        i += 1;
+    }
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> u32$0 {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return 55u32;
+            }
+            i += 3;
+        }
+        match i {
+            5 => return 99,
+            _ => return 0,
+        };
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+    if the_field < 5 {
+        let mut i = 0;
+        loop {
+            if i > 5 {
+                return Ok(55u32);
+            }
+            i += 3;
+        }
+        match i {
+            5 => return Ok(99),
+            _ => return Ok(0),
+        };
+    }
+    Ok(the_field)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> u3$02 {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return 99,
+            _ => return 0,
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+    if the_field < 5 {
+        let mut i = 0;
+        match i {
+            5 => return Ok(99),
+            _ => return Ok(0),
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> u32$0 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99
+        } else {
+            return 0
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Ok(99)
+        } else {
+            return Ok(0)
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo(the_field: u32) -> $0u32 {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return 99;
+        } else {
+            return 0;
+        }
+    }
+    the_field
+}
+"#,
+            r#"
+fn foo(the_field: u32) -> Result<u32, ${0:_}> {
+    if the_field < 5 {
+        let mut i = 0;
+        if i == 5 {
+            return Ok(99);
+        } else {
+            return Ok(0);
+        }
+    }
+    Ok(the_field)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_local_result_type() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+type Result<T> = core::result::Result<T, ()>;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+type Result<T> = core::result::Result<T, ()>;
+
+fn foo() -> Result<i32> {
+    return Ok(42i32);
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+type Result2<T> = core::result::Result<T, ()>;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+type Result2<T> = core::result::Result<T, ()>;
+
+fn foo() -> Result<i32, ${0:_}> {
+    return Ok(42i32);
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_imported_local_result_type() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+mod some_module {
+    pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::Result;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+mod some_module {
+    pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::Result;
+
+fn foo() -> Result<i32> {
+    return Ok(42i32);
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+mod some_module {
+    pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::*;
+
+fn foo() -> i3$02 {
+    return 42i32;
+}
+"#,
+            r#"
+mod some_module {
+    pub type Result<T> = core::result::Result<T, ()>;
+}
+
+use some_module::*;
+
+fn foo() -> Result<i32> {
+    return Ok(42i32);
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_local_result_type_from_function_body() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i3$02 {
+    type Result<T> = core::result::Result<T, ()>;
+    0
+}
+"#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    type Result<T> = core::result::Result<T, ()>;
+    Ok(0)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_local_result_type_already_using_alias() {
+        check_assist_not_applicable_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+pub type Result<T> = core::result::Result<T, ()>;
+
+fn foo() -> Result<i3$02> {
+    return Ok(42i32);
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+    }
+
+    #[test]
+    fn wrap_return_type_in_local_result_type_multiple_generics() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+type Result<T, E> = core::result::Result<T, E>;
+
+fn foo() -> i3$02 {
+    0
+}
+"#,
+            r#"
+type Result<T, E> = core::result::Result<T, E>;
+
+fn foo() -> Result<i32, ${0:_}> {
+    Ok(0)
+}
+"#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
+
+fn foo() -> i3$02 {
+    0
+}
+            "#,
+            r#"
+type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
+
+fn foo() -> Result<i32, ${0:_}> {
+    Ok(0)
+}
+            "#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
+
+fn foo() -> i3$02 {
+    0
+}
+            "#,
+            r#"
+type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
+
+fn foo() -> Result<'_, i32, ${0:_}> {
+    Ok(0)
+}
+            "#,
+            WrapperKind::Result.label(),
+        );
+
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
+
+fn foo() -> i3$02 {
+    0
+}
+            "#,
+            r#"
+type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
+
+fn foo() -> Result<i32, ${0:_}> {
+    Ok(0)
+}
+            "#,
+            WrapperKind::Result.label(),
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs
deleted file mode 100644
index 8f0e9b4fe09..00000000000
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs
+++ /dev/null
@@ -1,1268 +0,0 @@
-use std::iter;
-
-use hir::HasSource;
-use ide_db::{
-    famous_defs::FamousDefs,
-    syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
-};
-use itertools::Itertools;
-use syntax::{
-    ast::{self, make, Expr, HasGenericParams},
-    match_ast, ted, AstNode, ToSmolStr,
-};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists};
-
-// Assist: wrap_return_type_in_result
-//
-// Wrap the function's return type into Result.
-//
-// ```
-// # //- minicore: result
-// fn foo() -> i32$0 { 42i32 }
-// ```
-// ->
-// ```
-// fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
-// ```
-pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
-    let parent = ret_type.syntax().parent()?;
-    let body = match_ast! {
-        match parent {
-            ast::Fn(func) => func.body()?,
-            ast::ClosureExpr(closure) => match closure.body()? {
-                Expr::BlockExpr(block) => block,
-                // closures require a block when a return type is specified
-                _ => return None,
-            },
-            _ => return None,
-        }
-    };
-
-    let type_ref = &ret_type.ty()?;
-    let core_result =
-        FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?;
-
-    let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
-    if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == core_result) {
-        // The return type is already wrapped in a Result
-        cov_mark::hit!(wrap_return_type_in_result_simple_return_type_already_result);
-        return None;
-    }
-
-    acc.add(
-        AssistId("wrap_return_type_in_result", AssistKind::RefactorRewrite),
-        "Wrap return type in Result",
-        type_ref.syntax().text_range(),
-        |edit| {
-            let new_result_ty = result_type(ctx, &core_result, type_ref).clone_for_update();
-            let body = edit.make_mut(ast::Expr::BlockExpr(body));
-
-            let mut exprs_to_wrap = Vec::new();
-            let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e);
-            walk_expr(&body, &mut |expr| {
-                if let Expr::ReturnExpr(ret_expr) = expr {
-                    if let Some(ret_expr_arg) = &ret_expr.expr() {
-                        for_each_tail_expr(ret_expr_arg, tail_cb);
-                    }
-                }
-            });
-            for_each_tail_expr(&body, tail_cb);
-
-            for ret_expr_arg in exprs_to_wrap {
-                let ok_wrapped = make::expr_call(
-                    make::expr_path(make::ext::ident_path("Ok")),
-                    make::arg_list(iter::once(ret_expr_arg.clone())),
-                )
-                .clone_for_update();
-                ted::replace(ret_expr_arg.syntax(), ok_wrapped.syntax());
-            }
-
-            let old_result_ty = edit.make_mut(type_ref.clone());
-            ted::replace(old_result_ty.syntax(), new_result_ty.syntax());
-
-            // Add a placeholder snippet at the first generic argument that doesn't equal the return type.
-            // This is normally the error type, but that may not be the case when we inserted a type alias.
-            let args = new_result_ty.syntax().descendants().find_map(ast::GenericArgList::cast);
-            let error_type_arg = args.and_then(|list| {
-                list.generic_args().find(|arg| match arg {
-                    ast::GenericArg::TypeArg(_) => arg.syntax().text() != type_ref.syntax().text(),
-                    ast::GenericArg::LifetimeArg(_) => false,
-                    _ => true,
-                })
-            });
-            if let Some(error_type_arg) = error_type_arg {
-                if let Some(cap) = ctx.config.snippet_cap {
-                    edit.add_placeholder_snippet(cap, error_type_arg);
-                }
-            }
-        },
-    )
-}
-
-fn result_type(
-    ctx: &AssistContext<'_>,
-    core_result: &hir::Enum,
-    ret_type: &ast::Type,
-) -> ast::Type {
-    // Try to find a Result<T, ...> type alias in the current scope (shadowing the default).
-    let result_path = hir::ModPath::from_segments(
-        hir::PathKind::Plain,
-        iter::once(hir::Name::new_symbol_root(hir::sym::Result.clone())),
-    );
-    let alias = ctx.sema.resolve_mod_path(ret_type.syntax(), &result_path).and_then(|def| {
-        def.filter_map(|def| match def.as_module_def()? {
-            hir::ModuleDef::TypeAlias(alias) => {
-                let enum_ty = alias.ty(ctx.db()).as_adt()?.as_enum()?;
-                (&enum_ty == core_result).then_some(alias)
-            }
-            _ => None,
-        })
-        .find_map(|alias| {
-            let mut inserted_ret_type = false;
-            let generic_params = alias
-                .source(ctx.db())?
-                .value
-                .generic_param_list()?
-                .generic_params()
-                .map(|param| match param {
-                    // Replace the very first type parameter with the functions return type.
-                    ast::GenericParam::TypeParam(_) if !inserted_ret_type => {
-                        inserted_ret_type = true;
-                        ret_type.to_smolstr()
-                    }
-                    ast::GenericParam::LifetimeParam(_) => make::lifetime("'_").to_smolstr(),
-                    _ => make::ty_placeholder().to_smolstr(),
-                })
-                .join(", ");
-
-            let name = alias.name(ctx.db());
-            let name = name.as_str();
-            Some(make::ty(&format!("{name}<{generic_params}>")))
-        })
-    });
-    // If there is no applicable alias in scope use the default Result type.
-    alias.unwrap_or_else(|| make::ext::ty_result(ret_type.clone(), make::ty_placeholder()))
-}
-
-fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) {
-    match e {
-        Expr::BreakExpr(break_expr) => {
-            if let Some(break_expr_arg) = break_expr.expr() {
-                for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e))
-            }
-        }
-        Expr::ReturnExpr(_) => {
-            // all return expressions have already been handled by the walk loop
-        }
-        e => acc.push(e.clone()),
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
-
-    #[test]
-    fn wrap_return_type_in_result_simple() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i3$02 {
-    let test = "test";
-    return 42i32;
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let test = "test";
-    return Ok(42i32);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_break_split_tail() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i3$02 {
-    loop {
-        break if true {
-            1
-        } else {
-            0
-        };
-    }
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    loop {
-        break if true {
-            Ok(1)
-        } else {
-            Ok(0)
-        };
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_closure() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> i32$0 {
-        let test = "test";
-        return 42i32;
-    };
-}
-"#,
-            r#"
-fn foo() {
-    || -> Result<i32, ${0:_}> {
-        let test = "test";
-        return Ok(42i32);
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_return_type_bad_cursor() {
-        check_assist_not_applicable(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32 {
-    let test = "test";$0
-    return 42i32;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_return_type_bad_cursor_closure() {
-        check_assist_not_applicable(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> i32 {
-        let test = "test";$0
-        return 42i32;
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_closure_non_block() {
-        check_assist_not_applicable(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() { || -> i$032 3; }
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_return_type_already_result_std() {
-        check_assist_not_applicable(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> core::result::Result<i32$0, String> {
-    let test = "test";
-    return 42i32;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_return_type_already_result() {
-        cov_mark::check!(wrap_return_type_in_result_simple_return_type_already_result);
-        check_assist_not_applicable(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> Result<i32$0, String> {
-    let test = "test";
-    return 42i32;
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_return_type_already_result_closure() {
-        check_assist_not_applicable(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> Result<i32$0, String> {
-        let test = "test";
-        return 42i32;
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_cursor() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> $0i32 {
-    let test = "test";
-    return 42i32;
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let test = "test";
-    return Ok(42i32);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() ->$0 i32 {
-    let test = "test";
-    42i32
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let test = "test";
-    Ok(42i32)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail_closure() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() {
-    || ->$0 i32 {
-        let test = "test";
-        42i32
-    };
-}
-"#,
-            r#"
-fn foo() {
-    || -> Result<i32, ${0:_}> {
-        let test = "test";
-        Ok(42i32)
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail_only() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 { 42i32 }
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail_block_like() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    if true {
-        42i32
-    } else {
-        24i32
-    }
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    if true {
-        Ok(42i32)
-    } else {
-        Ok(24i32)
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_without_block_closure() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() {
-    || -> i32$0 {
-        if true {
-            42i32
-        } else {
-            24i32
-        }
-    };
-}
-"#,
-            r#"
-fn foo() {
-    || -> Result<i32, ${0:_}> {
-        if true {
-            Ok(42i32)
-        } else {
-            Ok(24i32)
-        }
-    };
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_nested_if() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    if true {
-        if false {
-            1
-        } else {
-            2
-        }
-    } else {
-        24i32
-    }
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    if true {
-        if false {
-            Ok(1)
-        } else {
-            Ok(2)
-        }
-    } else {
-        Ok(24i32)
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_await() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-async fn foo() -> i$032 {
-    if true {
-        if false {
-            1.await
-        } else {
-            2.await
-        }
-    } else {
-        24i32.await
-    }
-}
-"#,
-            r#"
-async fn foo() -> Result<i32, ${0:_}> {
-    if true {
-        if false {
-            Ok(1.await)
-        } else {
-            Ok(2.await)
-        }
-    } else {
-        Ok(24i32.await)
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_array() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> [i32;$0 3] { [1, 2, 3] }
-"#,
-            r#"
-fn foo() -> Result<[i32; 3], ${0:_}> { Ok([1, 2, 3]) }
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_cast() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -$0> i32 {
-    if true {
-        if false {
-            1 as i32
-        } else {
-            2 as i32
-        }
-    } else {
-        24 as i32
-    }
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    if true {
-        if false {
-            Ok(1 as i32)
-        } else {
-            Ok(2 as i32)
-        }
-    } else {
-        Ok(24 as i32)
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail_block_like_match() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let my_var = 5;
-    match my_var {
-        5 => 42i32,
-        _ => 24i32,
-    }
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let my_var = 5;
-    match my_var {
-        5 => Ok(42i32),
-        _ => Ok(24i32),
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_loop_with_tail() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let my_var = 5;
-    loop {
-        println!("test");
-        5
-    }
-    my_var
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let my_var = 5;
-    loop {
-        println!("test");
-        5
-    }
-    Ok(my_var)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_loop_in_let_stmt() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let my_var = let x = loop {
-        break 1;
-    };
-    my_var
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let my_var = let x = loop {
-        break 1;
-    };
-    Ok(my_var)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail_block_like_match_return_expr() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let my_var = 5;
-    let res = match my_var {
-        5 => 42i32,
-        _ => return 24i32,
-    };
-    res
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let my_var = 5;
-    let res = match my_var {
-        5 => 42i32,
-        _ => return Ok(24i32),
-    };
-    Ok(res)
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let my_var = 5;
-    let res = if my_var == 5 {
-        42i32
-    } else {
-        return 24i32;
-    };
-    res
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let my_var = 5;
-    let res = if my_var == 5 {
-        42i32
-    } else {
-        return Ok(24i32);
-    };
-    Ok(res)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail_block_like_match_deeper() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let my_var = 5;
-    match my_var {
-        5 => {
-            if true {
-                42i32
-            } else {
-                25i32
-            }
-        },
-        _ => {
-            let test = "test";
-            if test == "test" {
-                return bar();
-            }
-            53i32
-        },
-    }
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let my_var = 5;
-    match my_var {
-        5 => {
-            if true {
-                Ok(42i32)
-            } else {
-                Ok(25i32)
-            }
-        },
-        _ => {
-            let test = "test";
-            if test == "test" {
-                return Ok(bar());
-            }
-            Ok(53i32)
-        },
-    }
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_tail_block_like_early_return() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i$032 {
-    let test = "test";
-    if test == "test" {
-        return 24i32;
-    }
-    53i32
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let test = "test";
-    if test == "test" {
-        return Ok(24i32);
-    }
-    Ok(53i32)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_in_tail_position() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo(num: i32) -> $0i32 {
-    return num
-}
-"#,
-            r#"
-fn foo(num: i32) -> Result<i32, ${0:_}> {
-    return Ok(num)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_closure() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) ->$0 u32 {
-    let true_closure = || { return true; };
-    if the_field < 5 {
-        let mut i = 0;
-        if true_closure() {
-            return 99;
-        } else {
-            return 0;
-        }
-    }
-    the_field
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
-    let true_closure = || { return true; };
-    if the_field < 5 {
-        let mut i = 0;
-        if true_closure() {
-            return Ok(99);
-        } else {
-            return Ok(0);
-        }
-    }
-    Ok(the_field)
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> u32$0 {
-    let true_closure = || {
-        return true;
-    };
-    if the_field < 5 {
-        let mut i = 0;
-
-
-        if true_closure() {
-            return 99;
-        } else {
-            return 0;
-        }
-    }
-    let t = None;
-
-    t.unwrap_or_else(|| the_field)
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
-    let true_closure = || {
-        return true;
-    };
-    if the_field < 5 {
-        let mut i = 0;
-
-
-        if true_closure() {
-            return Ok(99);
-        } else {
-            return Ok(0);
-        }
-    }
-    let t = None;
-
-    Ok(t.unwrap_or_else(|| the_field))
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_result_simple_with_weird_forms() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i32$0 {
-    let test = "test";
-    if test == "test" {
-        return 24i32;
-    }
-    let mut i = 0;
-    loop {
-        if i == 1 {
-            break 55;
-        }
-        i += 1;
-    }
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    let test = "test";
-    if test == "test" {
-        return Ok(24i32);
-    }
-    let mut i = 0;
-    loop {
-        if i == 1 {
-            break Ok(55);
-        }
-        i += 1;
-    }
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> u32$0 {
-    if the_field < 5 {
-        let mut i = 0;
-        loop {
-            if i > 5 {
-                return 55u32;
-            }
-            i += 3;
-        }
-        match i {
-            5 => return 99,
-            _ => return 0,
-        };
-    }
-    the_field
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
-    if the_field < 5 {
-        let mut i = 0;
-        loop {
-            if i > 5 {
-                return Ok(55u32);
-            }
-            i += 3;
-        }
-        match i {
-            5 => return Ok(99),
-            _ => return Ok(0),
-        };
-    }
-    Ok(the_field)
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> u3$02 {
-    if the_field < 5 {
-        let mut i = 0;
-        match i {
-            5 => return 99,
-            _ => return 0,
-        }
-    }
-    the_field
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
-    if the_field < 5 {
-        let mut i = 0;
-        match i {
-            5 => return Ok(99),
-            _ => return Ok(0),
-        }
-    }
-    Ok(the_field)
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> u32$0 {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return 99
-        } else {
-            return 0
-        }
-    }
-    the_field
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return Ok(99)
-        } else {
-            return Ok(0)
-        }
-    }
-    Ok(the_field)
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo(the_field: u32) -> $0u32 {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return 99;
-        } else {
-            return 0;
-        }
-    }
-    the_field
-}
-"#,
-            r#"
-fn foo(the_field: u32) -> Result<u32, ${0:_}> {
-    if the_field < 5 {
-        let mut i = 0;
-        if i == 5 {
-            return Ok(99);
-        } else {
-            return Ok(0);
-        }
-    }
-    Ok(the_field)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_local_result_type() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-type Result<T> = core::result::Result<T, ()>;
-
-fn foo() -> i3$02 {
-    return 42i32;
-}
-"#,
-            r#"
-type Result<T> = core::result::Result<T, ()>;
-
-fn foo() -> Result<i32> {
-    return Ok(42i32);
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-type Result2<T> = core::result::Result<T, ()>;
-
-fn foo() -> i3$02 {
-    return 42i32;
-}
-"#,
-            r#"
-type Result2<T> = core::result::Result<T, ()>;
-
-fn foo() -> Result<i32, ${0:_}> {
-    return Ok(42i32);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_imported_local_result_type() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-mod some_module {
-    pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::Result;
-
-fn foo() -> i3$02 {
-    return 42i32;
-}
-"#,
-            r#"
-mod some_module {
-    pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::Result;
-
-fn foo() -> Result<i32> {
-    return Ok(42i32);
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-mod some_module {
-    pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::*;
-
-fn foo() -> i3$02 {
-    return 42i32;
-}
-"#,
-            r#"
-mod some_module {
-    pub type Result<T> = core::result::Result<T, ()>;
-}
-
-use some_module::*;
-
-fn foo() -> Result<i32> {
-    return Ok(42i32);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_local_result_type_from_function_body() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-fn foo() -> i3$02 {
-    type Result<T> = core::result::Result<T, ()>;
-    0
-}
-"#,
-            r#"
-fn foo() -> Result<i32, ${0:_}> {
-    type Result<T> = core::result::Result<T, ()>;
-    Ok(0)
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_local_result_type_already_using_alias() {
-        check_assist_not_applicable(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-pub type Result<T> = core::result::Result<T, ()>;
-
-fn foo() -> Result<i3$02> {
-    return Ok(42i32);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn wrap_return_type_in_local_result_type_multiple_generics() {
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-type Result<T, E> = core::result::Result<T, E>;
-
-fn foo() -> i3$02 {
-    0
-}
-"#,
-            r#"
-type Result<T, E> = core::result::Result<T, E>;
-
-fn foo() -> Result<i32, ${0:_}> {
-    Ok(0)
-}
-"#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
-
-fn foo() -> i3$02 {
-    0
-}
-            "#,
-            r#"
-type Result<T, E> = core::result::Result<Foo<T, E>, ()>;
-
-fn foo() -> Result<i32, ${0:_}> {
-    Ok(0)
-}
-            "#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
-
-fn foo() -> i3$02 {
-    0
-}
-            "#,
-            r#"
-type Result<'a, T, E> = core::result::Result<Foo<T, E>, &'a ()>;
-
-fn foo() -> Result<'_, i32, ${0:_}> {
-    Ok(0)
-}
-            "#,
-        );
-
-        check_assist(
-            wrap_return_type_in_result,
-            r#"
-//- minicore: result
-type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
-
-fn foo() -> i3$02 {
-    0
-}
-            "#,
-            r#"
-type Result<T, const N: usize> = core::result::Result<Foo<T>, Bar<N>>;
-
-fn foo() -> Result<i32, ${0:_}> {
-    Ok(0)
-}
-            "#,
-        );
-    }
-}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index c98655b4230..22620816d50 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -223,9 +223,9 @@ mod handlers {
     mod unnecessary_async;
     mod unqualify_method_call;
     mod unwrap_block;
-    mod unwrap_result_return_type;
+    mod unwrap_return_type;
     mod unwrap_tuple;
-    mod wrap_return_type_in_result;
+    mod wrap_return_type;
     mod wrap_unwrap_cfg_attr;
 
     pub(crate) fn all() -> &'static [Handler] {
@@ -355,10 +355,10 @@ mod handlers {
             unmerge_use::unmerge_use,
             unnecessary_async::unnecessary_async,
             unwrap_block::unwrap_block,
-            unwrap_result_return_type::unwrap_result_return_type,
+            unwrap_return_type::unwrap_return_type,
             unwrap_tuple::unwrap_tuple,
             unqualify_method_call::unqualify_method_call,
-            wrap_return_type_in_result::wrap_return_type_in_result,
+            wrap_return_type::wrap_return_type,
             wrap_unwrap_cfg_attr::wrap_unwrap_cfg_attr,
 
             // These are manually sorted for better priorities. By default,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 48e12a81073..933d45d7508 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -3265,6 +3265,20 @@ fn foo() {
 }
 
 #[test]
+fn doctest_unwrap_option_return_type() {
+    check_doc_test(
+        "unwrap_option_return_type",
+        r#####"
+//- minicore: option
+fn foo() -> Option<i32>$0 { Some(42i32) }
+"#####,
+        r#####"
+fn foo() -> i32 { 42i32 }
+"#####,
+    )
+}
+
+#[test]
 fn doctest_unwrap_result_return_type() {
     check_doc_test(
         "unwrap_result_return_type",
@@ -3298,6 +3312,20 @@ fn main() {
 }
 
 #[test]
+fn doctest_wrap_return_type_in_option() {
+    check_doc_test(
+        "wrap_return_type_in_option",
+        r#####"
+//- minicore: option
+fn foo() -> i32$0 { 42i32 }
+"#####,
+        r#####"
+fn foo() -> Option<i32> { Some(42i32) }
+"#####,
+    )
+}
+
+#[test]
 fn doctest_wrap_return_type_in_result() {
     check_doc_test(
         "wrap_return_type_in_result",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs
index 18833774083..3ab341e4ede 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs
@@ -29,7 +29,9 @@ pub(crate) fn complete_item_list(
     kind: &ItemListKind,
 ) {
     let _p = tracing::info_span!("complete_item_list").entered();
-    if path_ctx.is_trivial_path() {
+
+    // We handle completions for trait-impls in [`item_list::trait_impl`]
+    if path_ctx.is_trivial_path() && !matches!(kind, ItemListKind::TraitImpl(_)) {
         add_keywords(acc, ctx, Some(kind));
     }
 
@@ -75,73 +77,95 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
 
     let in_item_list = matches!(kind, Some(ItemListKind::SourceFile | ItemListKind::Module) | None);
     let in_assoc_non_trait_impl = matches!(kind, Some(ItemListKind::Impl | ItemListKind::Trait));
-    let in_extern_block = matches!(kind, Some(ItemListKind::ExternBlock));
+
+    let in_extern_block = matches!(kind, Some(ItemListKind::ExternBlock { .. }));
+    let in_unsafe_extern_block =
+        matches!(kind, Some(ItemListKind::ExternBlock { is_unsafe: true }));
+
     let in_trait = matches!(kind, Some(ItemListKind::Trait));
-    let in_trait_impl = matches!(kind, Some(ItemListKind::TraitImpl(_)));
     let in_inherent_impl = matches!(kind, Some(ItemListKind::Impl));
-    let no_vis_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
     let in_block = kind.is_none();
 
-    let missing_qualifiers = [
-        ctx.qualifier_ctx.unsafe_tok.is_none().then_some(("unsafe", "unsafe $0")),
-        ctx.qualifier_ctx.async_tok.is_none().then_some(("async", "async $0")),
-    ];
-
-    if !in_trait_impl {
-        // handle qualifier tokens
-        if missing_qualifiers.iter().any(Option::is_none) {
-            // only complete missing qualifiers
-            missing_qualifiers.iter().filter_map(|x| *x).for_each(|(kw, snippet)| {
-                add_keyword(kw, snippet);
-            });
-
-            if in_item_list || in_assoc_non_trait_impl {
-                add_keyword("fn", "fn $1($2) {\n    $0\n}");
-            }
+    let no_vis_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
+    let has_unsafe_kw = ctx.qualifier_ctx.unsafe_tok.is_some();
+    let has_async_kw = ctx.qualifier_ctx.async_tok.is_some();
+    let has_safe_kw = ctx.qualifier_ctx.safe_tok.is_some();
+
+    // Some keywords are invalid after non-vis qualifiers, so we handle them first.
+    if (has_unsafe_kw || has_safe_kw) && in_extern_block {
+        add_keyword("fn", "fn $1($2);");
+        add_keyword("static", "static $1: $2;");
+        return;
+    }
 
-            if ctx.qualifier_ctx.unsafe_tok.is_some() && in_item_list {
-                add_keyword("trait", "trait $1 {\n    $0\n}");
-                if no_vis_qualifiers {
-                    add_keyword("impl", "impl $1 {\n    $0\n}");
-                }
-            }
+    if has_unsafe_kw || has_async_kw {
+        if !has_unsafe_kw {
+            add_keyword("unsafe", "unsafe $0");
+        }
+        if !has_async_kw {
+            add_keyword("async", "async $0");
+        }
 
-            return;
+        if in_item_list || in_assoc_non_trait_impl {
+            add_keyword("fn", "fn $1($2) {\n    $0\n}");
         }
 
-        if in_item_list {
-            add_keyword("enum", "enum $1 {\n    $0\n}");
-            add_keyword("mod", "mod $0");
-            add_keyword("static", "static $0");
-            add_keyword("struct", "struct $0");
+        if has_unsafe_kw && in_item_list {
             add_keyword("trait", "trait $1 {\n    $0\n}");
-            add_keyword("union", "union $1 {\n    $0\n}");
-            add_keyword("use", "use $0");
             if no_vis_qualifiers {
                 add_keyword("impl", "impl $1 {\n    $0\n}");
             }
         }
 
-        if !in_trait && !in_block && no_vis_qualifiers {
-            add_keyword("pub(crate)", "pub(crate) $0");
-            add_keyword("pub(super)", "pub(super) $0");
-            add_keyword("pub", "pub $0");
+        if !has_async_kw && no_vis_qualifiers && in_item_list {
+            add_keyword("extern", "extern $0");
         }
 
-        if in_extern_block {
-            add_keyword("fn", "fn $1($2);");
-        } else {
-            if !in_inherent_impl {
-                if !in_trait {
-                    add_keyword("extern", "extern $0");
-                }
-                add_keyword("type", "type $0");
-            }
+        return;
+    }
 
-            add_keyword("fn", "fn $1($2) {\n    $0\n}");
-            add_keyword("unsafe", "unsafe $0");
-            add_keyword("const", "const $0");
-            add_keyword("async", "async $0");
+    // ...and the rest deals with cases without any non-vis qualifiers.
+
+    // Visibility qualifiers
+    if !in_trait && !in_block && no_vis_qualifiers {
+        add_keyword("pub(crate)", "pub(crate) $0");
+        add_keyword("pub(super)", "pub(super) $0");
+        add_keyword("pub", "pub $0");
+    }
+
+    // Keywords that are valid in `item_list`
+    if in_item_list {
+        add_keyword("enum", "enum $1 {\n    $0\n}");
+        add_keyword("mod", "mod $0");
+        add_keyword("static", "static $0");
+        add_keyword("struct", "struct $0");
+        add_keyword("trait", "trait $1 {\n    $0\n}");
+        add_keyword("union", "union $1 {\n    $0\n}");
+        add_keyword("use", "use $0");
+        if no_vis_qualifiers {
+            add_keyword("impl", "impl $1 {\n    $0\n}");
+        }
+    }
+
+    if in_extern_block {
+        add_keyword("unsafe", "unsafe $0");
+        if in_unsafe_extern_block {
+            add_keyword("safe", "safe $0");
         }
+
+        add_keyword("fn", "fn $1($2);");
+        add_keyword("static", "static $1: $2;");
+    } else {
+        if !in_inherent_impl {
+            if !in_trait {
+                add_keyword("extern", "extern $0");
+            }
+            add_keyword("type", "type $0");
+        }
+
+        add_keyword("fn", "fn $1($2) {\n    $0\n}");
+        add_keyword("unsafe", "unsafe $0");
+        add_keyword("const", "const $0");
+        add_keyword("async", "async $0");
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
index 0acb87872f5..71ca6e99494 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
@@ -58,6 +58,7 @@ mod tests {
             r"fn my_fn() { unsafe $0 }",
             expect![[r#"
                 kw async
+                kw extern
                 kw fn
                 kw impl
                 kw trait
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index e49a9e3b064..0e1302ff2ef 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -48,12 +48,16 @@ pub(crate) struct QualifierCtx {
     // TODO: Add try_tok and default_tok
     pub(crate) async_tok: Option<SyntaxToken>,
     pub(crate) unsafe_tok: Option<SyntaxToken>,
+    pub(crate) safe_tok: Option<SyntaxToken>,
     pub(crate) vis_node: Option<ast::Visibility>,
 }
 
 impl QualifierCtx {
     pub(crate) fn none(&self) -> bool {
-        self.async_tok.is_none() && self.unsafe_tok.is_none() && self.vis_node.is_none()
+        self.async_tok.is_none()
+            && self.unsafe_tok.is_none()
+            && self.safe_tok.is_none()
+            && self.vis_node.is_none()
     }
 }
 
@@ -229,7 +233,7 @@ pub(crate) enum ItemListKind {
     Impl,
     TraitImpl(Option<ast::Impl>),
     Trait,
-    ExternBlock,
+    ExternBlock { is_unsafe: bool },
 }
 
 #[derive(Debug)]
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 1f9e3edf625..468ad81ad2f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -1108,7 +1108,14 @@ fn classify_name_ref(
                     },
                     None => return None,
                 } },
-                ast::ExternItemList(_) => PathKind::Item { kind: ItemListKind::ExternBlock },
+                ast::ExternItemList(it) => {
+                    let exn_blk = it.syntax().parent().and_then(ast::ExternBlock::cast);
+                    PathKind::Item {
+                        kind: ItemListKind::ExternBlock {
+                            is_unsafe: exn_blk.and_then(|it| it.unsafe_token()).is_some(),
+                        }
+                    }
+                },
                 ast::SourceFile(_) => PathKind::Item { kind: ItemListKind::SourceFile },
                 _ => return None,
             }
@@ -1310,6 +1317,7 @@ fn classify_name_ref(
                         match token.kind() {
                             SyntaxKind::UNSAFE_KW => qualifier_ctx.unsafe_tok = Some(token),
                             SyntaxKind::ASYNC_KW => qualifier_ctx.async_tok = Some(token),
+                            SyntaxKind::SAFE_KW => qualifier_ctx.safe_tok = Some(token),
                             _ => {}
                         }
                     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index f2e9de9382c..4dd171142f9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -1853,8 +1853,8 @@ fn f() { A { bar: b$0 }; }
             expect![[r#"
                 fn bar() [type+name]
                 fn baz() [type]
-                ex baz() [type]
                 ex bar() [type]
+                ex baz() [type]
                 st A []
                 fn f() []
             "#]],
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
index 532d4928eff..dfef8fa472d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
@@ -124,6 +124,7 @@ fn after_unsafe_token() {
         r#"unsafe $0"#,
         expect![[r#"
             kw async
+            kw extern
             kw fn
             kw impl
             kw trait
@@ -495,3 +496,57 @@ type O = $0;
 ",
     )
 }
+
+#[test]
+fn inside_extern_blocks() {
+    // Should suggest `fn`, `static`, `unsafe`
+    check(
+        r#"extern { $0 }"#,
+        expect![[r#"
+            ma makro!(…)  macro_rules! makro
+            md module
+            kw crate::
+            kw fn
+            kw pub
+            kw pub(crate)
+            kw pub(super)
+            kw self::
+            kw static
+            kw unsafe
+        "#]],
+    );
+
+    // Should suggest `fn`, `static`, `safe`, `unsafe`
+    check(
+        r#"unsafe extern { $0 }"#,
+        expect![[r#"
+            ma makro!(…)  macro_rules! makro
+            md module
+            kw crate::
+            kw fn
+            kw pub
+            kw pub(crate)
+            kw pub(super)
+            kw safe
+            kw self::
+            kw static
+            kw unsafe
+        "#]],
+    );
+
+    check(
+        r#"unsafe extern { pub safe $0 }"#,
+        expect![[r#"
+            kw fn
+            kw static
+        "#]],
+    );
+
+    check(
+        r#"unsafe extern { pub unsafe $0 }"#,
+        expect![[r#"
+            kw fn
+            kw static
+        "#]],
+    )
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
index bd3e7c72bcd..a5eb0369b14 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
@@ -923,3 +923,21 @@ fn foo() {
         "#]],
     );
 }
+
+#[test]
+fn private_item_in_module_in_function_body() {
+    check_empty(
+        r#"
+fn main() {
+    mod foo {
+        struct Private;
+        pub struct Public;
+    }
+    foo::$0
+}
+"#,
+        expect![[r#"
+            st Public Public
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index 5b43f4b2af3..44be53b87ca 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -595,4 +595,39 @@ unsafe fn foo(p: *mut i32) {
             "#,
         )
     }
+
+    #[test]
+    fn no_unsafe_diagnostic_with_safe_kw() {
+        check_diagnostics(
+            r#"
+unsafe extern {
+    pub safe fn f();
+
+    pub unsafe fn g();
+
+    pub fn h();
+
+    pub safe static S1: i32;
+
+    pub unsafe static S2: i32;
+
+    pub static S3: i32;
+}
+
+fn main() {
+    f();
+    g();
+  //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+    h();
+  //^^^💡 error: this operation is unsafe and requires an unsafe function or block
+
+    let _ = S1;
+    let _ = S2;
+          //^^💡 error: this operation is unsafe and requires an unsafe function or block
+    let _ = S3;
+          //^^💡 error: this operation is unsafe and requires an unsafe function or block
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
index 8e0166a4a76..121a463c9f1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
@@ -288,6 +288,20 @@ fn main() {
                     },
                     Annotation {
                         range: 53..57,
+                        kind: HasReferences {
+                            pos: FilePositionWrapper {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                offset: 53,
+                            },
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
+                    Annotation {
+                        range: 53..57,
                         kind: Runnable(
                             Runnable {
                                 use_name_in_title: false,
@@ -305,20 +319,6 @@ fn main() {
                             },
                         ),
                     },
-                    Annotation {
-                        range: 53..57,
-                        kind: HasReferences {
-                            pos: FilePositionWrapper {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                offset: 53,
-                            },
-                            data: Some(
-                                [],
-                            ),
-                        },
-                    },
                 ]
             "#]],
         );
@@ -338,6 +338,20 @@ fn main() {
                 [
                     Annotation {
                         range: 7..11,
+                        kind: HasImpls {
+                            pos: FilePositionWrapper {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                offset: 7,
+                            },
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
+                    Annotation {
+                        range: 7..11,
                         kind: HasReferences {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
@@ -358,13 +372,13 @@ fn main() {
                         },
                     },
                     Annotation {
-                        range: 7..11,
-                        kind: HasImpls {
+                        range: 17..21,
+                        kind: HasReferences {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
-                                offset: 7,
+                                offset: 17,
                             },
                             data: Some(
                                 [],
@@ -390,20 +404,6 @@ fn main() {
                             },
                         ),
                     },
-                    Annotation {
-                        range: 17..21,
-                        kind: HasReferences {
-                            pos: FilePositionWrapper {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                offset: 17,
-                            },
-                            data: Some(
-                                [],
-                            ),
-                        },
-                    },
                 ]
             "#]],
         );
@@ -427,7 +427,7 @@ fn main() {
                 [
                     Annotation {
                         range: 7..11,
-                        kind: HasReferences {
+                        kind: HasImpls {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
@@ -436,17 +436,14 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 57..61,
-                                    },
-                                    FileRangeWrapper {
+                                    NavigationTarget {
                                         file_id: FileId(
                                             0,
                                         ),
-                                        range: 93..97,
+                                        full_range: 36..64,
+                                        focus_range: 57..61,
+                                        name: "impl",
+                                        kind: Impl,
                                     },
                                 ],
                             ),
@@ -454,7 +451,7 @@ fn main() {
                     },
                     Annotation {
                         range: 7..11,
-                        kind: HasImpls {
+                        kind: HasReferences {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
@@ -463,14 +460,17 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    NavigationTarget {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
-                                        full_range: 36..64,
-                                        focus_range: 57..61,
-                                        name: "impl",
-                                        kind: Impl,
+                                        range: 57..61,
+                                    },
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 93..97,
                                     },
                                 ],
                             ),
@@ -523,20 +523,6 @@ fn main() {
                     },
                     Annotation {
                         range: 69..73,
-                        kind: HasReferences {
-                            pos: FilePositionWrapper {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                offset: 69,
-                            },
-                            data: Some(
-                                [],
-                            ),
-                        },
-                    },
-                    Annotation {
-                        range: 69..73,
                         kind: Runnable(
                             Runnable {
                                 use_name_in_title: false,
@@ -554,6 +540,20 @@ fn main() {
                             },
                         ),
                     },
+                    Annotation {
+                        range: 69..73,
+                        kind: HasReferences {
+                            pos: FilePositionWrapper {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                offset: 69,
+                            },
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
                 ]
             "#]],
         );
@@ -569,6 +569,20 @@ fn main() {}
                 [
                     Annotation {
                         range: 3..7,
+                        kind: HasReferences {
+                            pos: FilePositionWrapper {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                offset: 3,
+                            },
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
+                    Annotation {
+                        range: 3..7,
                         kind: Runnable(
                             Runnable {
                                 use_name_in_title: false,
@@ -586,20 +600,6 @@ fn main() {}
                             },
                         ),
                     },
-                    Annotation {
-                        range: 3..7,
-                        kind: HasReferences {
-                            pos: FilePositionWrapper {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                offset: 3,
-                            },
-                            data: Some(
-                                [],
-                            ),
-                        },
-                    },
                 ]
             "#]],
         );
@@ -623,7 +623,7 @@ fn main() {
                 [
                     Annotation {
                         range: 7..11,
-                        kind: HasReferences {
+                        kind: HasImpls {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
@@ -632,17 +632,14 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 19..23,
-                                    },
-                                    FileRangeWrapper {
+                                    NavigationTarget {
                                         file_id: FileId(
                                             0,
                                         ),
-                                        range: 74..78,
+                                        full_range: 14..56,
+                                        focus_range: 19..23,
+                                        name: "impl",
+                                        kind: Impl,
                                     },
                                 ],
                             ),
@@ -650,7 +647,7 @@ fn main() {
                     },
                     Annotation {
                         range: 7..11,
-                        kind: HasImpls {
+                        kind: HasReferences {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
@@ -659,14 +656,17 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    NavigationTarget {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
-                                        full_range: 14..56,
-                                        focus_range: 19..23,
-                                        name: "impl",
-                                        kind: Impl,
+                                        range: 19..23,
+                                    },
+                                    FileRangeWrapper {
+                                        file_id: FileId(
+                                            0,
+                                        ),
+                                        range: 74..78,
                                     },
                                 ],
                             ),
@@ -695,20 +695,6 @@ fn main() {
                     },
                     Annotation {
                         range: 61..65,
-                        kind: HasReferences {
-                            pos: FilePositionWrapper {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                offset: 61,
-                            },
-                            data: Some(
-                                [],
-                            ),
-                        },
-                    },
-                    Annotation {
-                        range: 61..65,
                         kind: Runnable(
                             Runnable {
                                 use_name_in_title: false,
@@ -726,6 +712,20 @@ fn main() {
                             },
                         ),
                     },
+                    Annotation {
+                        range: 61..65,
+                        kind: HasReferences {
+                            pos: FilePositionWrapper {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                offset: 61,
+                            },
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
                 ]
             "#]],
         );
@@ -746,20 +746,6 @@ mod tests {
                 [
                     Annotation {
                         range: 3..7,
-                        kind: HasReferences {
-                            pos: FilePositionWrapper {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                offset: 3,
-                            },
-                            data: Some(
-                                [],
-                            ),
-                        },
-                    },
-                    Annotation {
-                        range: 3..7,
                         kind: Runnable(
                             Runnable {
                                 use_name_in_title: false,
@@ -778,6 +764,20 @@ mod tests {
                         ),
                     },
                     Annotation {
+                        range: 3..7,
+                        kind: HasReferences {
+                            pos: FilePositionWrapper {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                offset: 3,
+                            },
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
+                    Annotation {
                         range: 18..23,
                         kind: Runnable(
                             Runnable {
@@ -876,7 +876,7 @@ struct Foo;
                 [
                     Annotation {
                         range: 0..71,
-                        kind: HasReferences {
+                        kind: HasImpls {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
@@ -890,7 +890,7 @@ struct Foo;
                     },
                     Annotation {
                         range: 0..71,
-                        kind: HasImpls {
+                        kind: HasReferences {
                             pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index c61b2ba84f2..4cbcb6ed050 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -505,6 +505,44 @@ fn foo() {
     }
 
     #[test]
+    fn goto_def_in_included_file_inside_mod() {
+        check(
+            r#"
+//- minicore:include
+//- /main.rs
+mod a {
+    include!("b.rs");
+}
+//- /b.rs
+fn func_in_include() {
+ //^^^^^^^^^^^^^^^
+}
+fn foo() {
+    func_in_include$0();
+}
+"#,
+        );
+
+        check(
+            r#"
+//- minicore:include
+//- /main.rs
+mod a {
+    include!("a.rs");
+}
+//- /a.rs
+fn func_in_include() {
+ //^^^^^^^^^^^^^^^
+}
+
+fn foo() {
+    func_in_include$0();
+}
+"#,
+        );
+    }
+
+    #[test]
     fn goto_def_if_items_same_name() {
         check(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 64d717f88dd..e7cb8a253f4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -2750,4 +2750,25 @@ impl Foo {
             "#]],
         );
     }
+
+    #[test]
+    fn goto_ref_on_included_file() {
+        check(
+            r#"
+//- minicore:include
+//- /lib.rs
+include!("foo.rs");
+fn howdy() {
+    let _ = FOO;
+}
+//- /foo.rs
+const FOO$0: i32 = 0;
+"#,
+            expect![[r#"
+                FOO Const FileId(1) 0..19 6..9
+
+                FileId(0) 45..48
+            "#]],
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index 38dc522789d..3bbbd36c1b1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -1350,18 +1350,18 @@ mod tests {
                         file_id: FileId(
                             0,
                         ),
-                        full_range: 121..185,
-                        focus_range: 136..145,
-                        name: "foo2_test",
+                        full_range: 52..115,
+                        focus_range: 67..75,
+                        name: "foo_test",
                         kind: Function,
                     },
                     NavigationTarget {
                         file_id: FileId(
                             0,
                         ),
-                        full_range: 52..115,
-                        focus_range: 67..75,
-                        name: "foo_test",
+                        full_range: 121..185,
+                        focus_range: 136..145,
+                        name: "foo2_test",
                         kind: Function,
                     },
                 ]
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
index 5d51b149789..a4449b5d8d8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
@@ -46,14 +46,14 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="17360984456076382725" style="color: hsl(95,79%,86%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="17186414787327620935" style="color: hsl(196,64%,89%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="10753541418856619067" style="color: hsl(51,52%,47%);">x</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="9865812862466303869" style="color: hsl(329,86%,55%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
-    <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="4786021388930833562" style="color: hsl(137,61%,87%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="18017815841345165192" style="color: hsl(39,76%,89%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="4786021388930833562" style="color: hsl(137,61%,87%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="4890670724659097491" style="color: hsl(330,46%,45%);">x</span> <span class="operator">=</span> <span class="string_literal">"other color please!"</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="4002942168268782293" style="color: hsl(114,87%,67%);">y</span> <span class="operator">=</span> <span class="variable reference" data-binding-hash="4890670724659097491" style="color: hsl(330,46%,45%);">x</span><span class="operator">.</span><span class="unresolved_reference">to_string</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">bar</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="8384512769119783714" style="color: hsl(59,93%,58%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable reference" data-binding-hash="16711699953829236520" style="color: hsl(345,54%,46%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index 9e4ef140740..270bc05a4ee 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
@@ -3,6 +3,7 @@
 use intern::Symbol;
 use rustc_hash::FxHashMap;
 use span::{Edition, Span};
+use stdx::itertools::Itertools;
 use syntax::{
     ast::{self, HasName},
     AstNode,
@@ -27,9 +28,10 @@ fn benchmark_parse_macro_rules() {
     let hash: usize = {
         let _pt = bench("mbe parse macro rules");
         rules
-            .values()
-            .map(|it| {
-                DeclarativeMacro::parse_macro_rules(it, |_| span::Edition::CURRENT).rules.len()
+            .into_iter()
+            .sorted_by_key(|(id, _)| id.clone())
+            .map(|(_, it)| {
+                DeclarativeMacro::parse_macro_rules(&it, |_| span::Edition::CURRENT).rules.len()
             })
             .sum()
     };
@@ -55,12 +57,13 @@ fn benchmark_expand_macro_rules() {
             })
             .sum()
     };
-    assert_eq!(hash, 69413);
+    assert_eq!(hash, 65720);
 }
 
 fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro> {
     macro_rules_fixtures_tt()
         .into_iter()
+        .sorted_by_key(|(id, _)| id.clone())
         .map(|(id, tt)| (id, DeclarativeMacro::parse_macro_rules(&tt, |_| span::Edition::CURRENT)))
         .collect()
 }
@@ -93,7 +96,7 @@ fn invocation_fixtures(
     let mut seed = 123456789;
     let mut res = Vec::new();
 
-    for (name, it) in rules {
+    for (name, it) in rules.iter().sorted_by_key(|&(id, _)| id) {
         for rule in it.rules.iter() {
             // Generate twice
             for _ in 0..2 {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
index 4e2a50d7a1f..c4dce0daa5b 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
@@ -135,6 +135,11 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
         has_mods = true;
     }
 
+    if p.at_contextual_kw(T![safe]) {
+        p.eat_contextual_kw(T![safe]);
+        has_mods = true;
+    }
+
     if p.at(T![extern]) {
         has_extern = true;
         has_mods = true;
@@ -189,6 +194,7 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
         T![fn] => fn_(p, m),
 
         T![const] if p.nth(1) != T!['{'] => consts::konst(p, m),
+        T![static] if matches!(p.nth(1), IDENT | T![_] | T![mut]) => consts::static_(p, m),
 
         T![trait] => traits::trait_(p, m),
         T![impl] => traits::impl_(p, m),
diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
index 288a07ef44d..8da338c0a2c 100644
--- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
@@ -136,6 +136,7 @@ pub enum SyntaxKind {
     PURE_KW,
     RAW_KW,
     READONLY_KW,
+    SAFE_KW,
     SYM_KW,
     TRY_KW,
     UNION_KW,
@@ -416,6 +417,7 @@ impl SyntaxKind {
             PURE_KW => true,
             RAW_KW => true,
             READONLY_KW => true,
+            SAFE_KW => true,
             SYM_KW => true,
             UNION_KW => true,
             YEET_KW => true,
@@ -503,6 +505,7 @@ impl SyntaxKind {
             PURE_KW => true,
             RAW_KW => true,
             READONLY_KW => true,
+            SAFE_KW => true,
             SYM_KW => true,
             UNION_KW => true,
             YEET_KW => true,
@@ -664,6 +667,7 @@ impl SyntaxKind {
             "pure" => PURE_KW,
             "raw" => RAW_KW,
             "readonly" => READONLY_KW,
+            "safe" => SAFE_KW,
             "sym" => SYM_KW,
             "union" => UNION_KW,
             "yeet" => YEET_KW,
@@ -707,4 +711,4 @@ impl SyntaxKind {
     }
 }
 #[macro_export]
-macro_rules ! T { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
+macro_rules ! T { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [safe] => { $ crate :: SyntaxKind :: SAFE_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast
new file mode 100644
index 00000000000..b3d9e558067
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rast
@@ -0,0 +1,208 @@
+SOURCE_FILE
+  EXTERN_BLOCK
+    UNSAFE_KW "unsafe"
+    WHITESPACE " "
+    ABI
+      EXTERN_KW "extern"
+    WHITESPACE " "
+    EXTERN_ITEM_LIST
+      L_CURLY "{"
+      WHITESPACE "\n    "
+      FN
+        COMMENT "// sqrt (from libm) may be called with any `f64`"
+        WHITESPACE "\n    "
+        VISIBILITY
+          PUB_KW "pub"
+        WHITESPACE " "
+        SAFE_KW "safe"
+        WHITESPACE " "
+        FN_KW "fn"
+        WHITESPACE " "
+        NAME
+          IDENT "sqrt"
+        PARAM_LIST
+          L_PAREN "("
+          PARAM
+            IDENT_PAT
+              NAME
+                IDENT "x"
+            COLON ":"
+            WHITESPACE " "
+            PATH_TYPE
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "f64"
+          R_PAREN ")"
+        WHITESPACE " "
+        RET_TYPE
+          THIN_ARROW "->"
+          WHITESPACE " "
+          PATH_TYPE
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "f64"
+        SEMICOLON ";"
+      WHITESPACE "\n\n    "
+      FN
+        COMMENT "// strlen (from libc) requires a valid pointer,"
+        WHITESPACE "\n    "
+        COMMENT "// so we mark it as being an unsafe fn"
+        WHITESPACE "\n    "
+        VISIBILITY
+          PUB_KW "pub"
+        WHITESPACE " "
+        UNSAFE_KW "unsafe"
+        WHITESPACE " "
+        FN_KW "fn"
+        WHITESPACE " "
+        NAME
+          IDENT "strlen"
+        PARAM_LIST
+          L_PAREN "("
+          PARAM
+            IDENT_PAT
+              NAME
+                IDENT "p"
+            COLON ":"
+            WHITESPACE " "
+            PTR_TYPE
+              STAR "*"
+              CONST_KW "const"
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "c_char"
+          R_PAREN ")"
+        WHITESPACE " "
+        RET_TYPE
+          THIN_ARROW "->"
+          WHITESPACE " "
+          PATH_TYPE
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "usize"
+        SEMICOLON ";"
+      WHITESPACE "\n\n    "
+      FN
+        COMMENT "// this function doesn't say safe or unsafe, so it defaults to unsafe"
+        WHITESPACE "\n    "
+        VISIBILITY
+          PUB_KW "pub"
+        WHITESPACE " "
+        FN_KW "fn"
+        WHITESPACE " "
+        NAME
+          IDENT "free"
+        PARAM_LIST
+          L_PAREN "("
+          PARAM
+            IDENT_PAT
+              NAME
+                IDENT "p"
+            COLON ":"
+            WHITESPACE " "
+            PTR_TYPE
+              STAR "*"
+              MUT_KW "mut"
+              WHITESPACE " "
+              PATH_TYPE
+                PATH
+                  PATH
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "core"
+                    COLON2 "::"
+                    PATH_SEGMENT
+                      NAME_REF
+                        IDENT "ffi"
+                  COLON2 "::"
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "c_void"
+          R_PAREN ")"
+        SEMICOLON ";"
+      WHITESPACE "\n\n    "
+      STATIC
+        VISIBILITY
+          PUB_KW "pub"
+        WHITESPACE " "
+        SAFE_KW "safe"
+        WHITESPACE " "
+        STATIC_KW "static"
+        WHITESPACE " "
+        MUT_KW "mut"
+        WHITESPACE " "
+        NAME
+          IDENT "COUNTER"
+        COLON ":"
+        WHITESPACE " "
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "i32"
+        SEMICOLON ";"
+      WHITESPACE "\n\n    "
+      STATIC
+        VISIBILITY
+          PUB_KW "pub"
+        WHITESPACE " "
+        UNSAFE_KW "unsafe"
+        WHITESPACE " "
+        STATIC_KW "static"
+        WHITESPACE " "
+        NAME
+          IDENT "IMPORTANT_BYTES"
+        COLON ":"
+        WHITESPACE " "
+        ARRAY_TYPE
+          L_BRACK "["
+          PATH_TYPE
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "u8"
+          SEMICOLON ";"
+          WHITESPACE " "
+          CONST_ARG
+            LITERAL
+              INT_NUMBER "256"
+          R_BRACK "]"
+        SEMICOLON ";"
+      WHITESPACE "\n\n    "
+      STATIC
+        VISIBILITY
+          PUB_KW "pub"
+        WHITESPACE " "
+        SAFE_KW "safe"
+        WHITESPACE " "
+        STATIC_KW "static"
+        WHITESPACE " "
+        NAME
+          IDENT "LINES"
+        COLON ":"
+        WHITESPACE " "
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "SyncUnsafeCell"
+              GENERIC_ARG_LIST
+                L_ANGLE "<"
+                TYPE_ARG
+                  PATH_TYPE
+                    PATH
+                      PATH_SEGMENT
+                        NAME_REF
+                          IDENT "i32"
+                R_ANGLE ">"
+        SEMICOLON ";"
+      WHITESPACE "\n"
+      R_CURLY "}"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs
new file mode 100644
index 00000000000..267a128649c
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0073_safe_declarations_in_extern_blocks.rs
@@ -0,0 +1,17 @@
+unsafe extern {
+    // sqrt (from libm) may be called with any `f64`
+    pub safe fn sqrt(x: f64) -> f64;
+
+    // strlen (from libc) requires a valid pointer,
+    // so we mark it as being an unsafe fn
+    pub unsafe fn strlen(p: *const c_char) -> usize;
+
+    // this function doesn't say safe or unsafe, so it defaults to unsafe
+    pub fn free(p: *mut core::ffi::c_void);
+
+    pub safe static mut COUNTER: i32;
+
+    pub unsafe static IMPORTANT_BYTES: [u8; 256];
+
+    pub safe static LINES: SyncUnsafeCell<i32>;
+}
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index 5099697a696..ef115494a88 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -222,8 +222,6 @@ fn rust_project_is_proc_macro_has_proc_macro_dep() {
 }
 
 #[test]
-// FIXME Remove the ignore
-#[ignore = "requires nightly until the sysroot ships a cargo workspace for library on stable"]
 fn smoke_test_real_sysroot_cargo() {
     let file_map = &mut FxHashMap::<AbsPathBuf, FileId>::default();
     let meta: Metadata = get_test_json_file("hello-world-metadata.json");
@@ -235,7 +233,6 @@ fn smoke_test_real_sysroot_cargo() {
         &Default::default(),
     );
     assert!(matches!(sysroot.mode(), SysrootMode::Workspace(_)));
-
     let project_workspace = ProjectWorkspace {
         kind: ProjectWorkspaceKind::Cargo {
             cargo: cargo_workspace,
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml b/src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml
index b81e780337f..f8a3156fe40 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ra-salsa/Cargo.toml
@@ -17,7 +17,7 @@ indexmap = "2.1.0"
 lock_api = "0.4"
 tracing = "0.1"
 parking_lot = "0.12.1"
-rustc-hash = "1.0"
+rustc-hash = "2.0.0"
 smallvec = "1.0.0"
 oorandom = "11"
 triomphe = "0.1.11"
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index c2164614274..51c81a0d1a6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -6,6 +6,7 @@ use std::{
     time::{SystemTime, UNIX_EPOCH},
 };
 
+use cfg::{CfgAtom, CfgDiff};
 use hir::{
     db::{DefDatabase, ExpandDatabase, HirDatabase},
     Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, HirFileIdExt, ImportPathConfig,
@@ -31,7 +32,7 @@ use itertools::Itertools;
 use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
 use oorandom::Rand32;
 use profile::{Bytes, StopWatch};
-use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource};
+use project_model::{CargoConfig, CfgOverrides, ProjectManifest, ProjectWorkspace, RustLibSource};
 use rayon::prelude::*;
 use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::{AstNode, SyntaxNode};
@@ -65,7 +66,11 @@ impl flags::AnalysisStats {
                 false => Some(RustLibSource::Discover),
             },
             all_targets: true,
-            set_test: true,
+            set_test: !self.no_test,
+            cfg_overrides: CfgOverrides {
+                global: CfgDiff::new(vec![CfgAtom::Flag(hir::sym::miri.clone())], vec![]).unwrap(),
+                selective: Default::default(),
+            },
             ..Default::default()
         };
         let no_progress = &|_| ();
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
index 60d621b214a..ff24602144a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
@@ -71,6 +71,8 @@ xflags::xflags! {
             optional --with-deps
             /// Don't load sysroot crates (`std`, `core` & friends).
             optional --no-sysroot
+            /// Don't set #[cfg(test)].
+            optional --no-test
 
             /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
             optional --disable-build-scripts
@@ -233,6 +235,7 @@ pub struct AnalysisStats {
     pub only: Option<String>,
     pub with_deps: bool,
     pub no_sysroot: bool,
+    pub no_test: bool,
     pub disable_build_scripts: bool,
     pub disable_proc_macros: bool,
     pub proc_macro_srv: Option<PathBuf>,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
index 1f4544887f0..47e9961cf13 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
@@ -35,10 +35,18 @@ pub(crate) fn offset(
                 .ok_or_else(|| format_err!("Invalid wide col offset"))?
         }
     };
-    let text_size = line_index.index.offset(line_col).ok_or_else(|| {
+    let line_range = line_index.index.line(line_col.line).ok_or_else(|| {
         format_err!("Invalid offset {line_col:?} (line index length: {:?})", line_index.index.len())
     })?;
-    Ok(text_size)
+    let col = TextSize::from(line_col.col);
+    let clamped_len = col.min(line_range.len());
+    if clamped_len < col {
+        tracing::error!(
+            "Position {line_col:?} column exceeds line length {}, clamping it",
+            u32::from(line_range.len()),
+        );
+    }
+    Ok(line_range.start() + clamped_len)
 }
 
 pub(crate) fn text_range(
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index 52ad439e4de..90441c27f62 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -190,7 +190,7 @@ UseTreeList =
 
 Fn =
  Attr* Visibility?
- 'default'? 'const'? 'async'? 'gen'? 'unsafe'? Abi?
+ 'default'? 'const'? 'async'? 'gen'? 'unsafe'? 'safe'? Abi?
  'fn' Name GenericParamList? ParamList RetType? WhereClause?
  (body:BlockExpr | ';')
 
@@ -284,6 +284,7 @@ Const =
 
 Static =
   Attr* Visibility?
+  'unsafe'? 'safe'?
   'static' 'mut'? Name ':' Type
   ('=' body:Expr)? ';'
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index c81a19f3bda..4f8bff489cf 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -668,6 +668,8 @@ impl Fn {
     #[inline]
     pub fn gen_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![gen]) }
     #[inline]
+    pub fn safe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![safe]) }
+    #[inline]
     pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
@@ -1761,7 +1763,11 @@ impl Static {
     #[inline]
     pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
     #[inline]
+    pub fn safe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![safe]) }
+    #[inline]
     pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
+    #[inline]
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ptr.rs b/src/tools/rust-analyzer/crates/syntax/src/ptr.rs
index ed4894f9b9c..11b79e4e0ed 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ptr.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ptr.rs
@@ -27,7 +27,7 @@ pub struct AstPtr<N: AstNode> {
     _ty: PhantomData<fn() -> N>,
 }
 
-impl<N: AstNode + std::fmt::Debug> std::fmt::Debug for AstPtr<N> {
+impl<N: AstNode> std::fmt::Debug for AstPtr<N> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_tuple("AstPtr").field(&self.raw).finish()
     }
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index babeb4272be..463718835b9 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -95,8 +95,8 @@ avoid checking unnecessary things.
 Default:
 ----
 {
-  "debug_assertions": null,
-  "miri": null
+  "miri": null,
+  "debug_assertions": null
 }
 ----
 List of cfg options to enable with the given values.
@@ -321,18 +321,10 @@ Enables completions of private items and fields that are defined in the current
 Default:
 ----
 {
-  "Arc::new": {
-    "postfix": "arc",
-    "body": "Arc::new(${receiver})",
-    "requires": "std::sync::Arc",
-    "description": "Put the expression into an `Arc`",
-    "scope": "expr"
-  },
-  "Rc::new": {
-    "postfix": "rc",
-    "body": "Rc::new(${receiver})",
-    "requires": "std::rc::Rc",
-    "description": "Put the expression into an `Rc`",
+  "Ok": {
+    "postfix": "ok",
+    "body": "Ok(${receiver})",
+    "description": "Wrap the expression in a `Result::Ok`",
     "scope": "expr"
   },
   "Box::pin": {
@@ -342,10 +334,11 @@ Default:
     "description": "Put the expression into a pinned `Box`",
     "scope": "expr"
   },
-  "Err": {
-    "postfix": "err",
-    "body": "Err(${receiver})",
-    "description": "Wrap the expression in a `Result::Err`",
+  "Arc::new": {
+    "postfix": "arc",
+    "body": "Arc::new(${receiver})",
+    "requires": "std::sync::Arc",
+    "description": "Put the expression into an `Arc`",
     "scope": "expr"
   },
   "Some": {
@@ -354,10 +347,17 @@ Default:
     "description": "Wrap the expression in an `Option::Some`",
     "scope": "expr"
   },
-  "Ok": {
-    "postfix": "ok",
-    "body": "Ok(${receiver})",
-    "description": "Wrap the expression in a `Result::Ok`",
+  "Err": {
+    "postfix": "err",
+    "body": "Err(${receiver})",
+    "description": "Wrap the expression in a `Result::Err`",
+    "scope": "expr"
+  },
+  "Rc::new": {
+    "postfix": "rc",
+    "body": "Rc::new(${receiver})",
+    "requires": "std::rc::Rc",
+    "description": "Put the expression into an `Rc`",
     "scope": "expr"
   }
 }
diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json
index 7de75763177..10b633511d3 100644
--- a/src/tools/rust-analyzer/editors/code/package-lock.json
+++ b/src/tools/rust-analyzer/editors/code/package-lock.json
@@ -22,14 +22,14 @@
                 "@typescript-eslint/eslint-plugin": "^6.0.0",
                 "@typescript-eslint/parser": "^6.0.0",
                 "@vscode/test-electron": "^2.3.8",
-                "@vscode/vsce": "^2.19.0",
+                "@vscode/vsce": "^3.0.0",
                 "esbuild": "^0.18.12",
                 "eslint": "^8.44.0",
                 "eslint-config-prettier": "^8.8.0",
                 "ovsx": "^0.8.2",
                 "prettier": "^3.0.0",
                 "tslib": "^2.6.0",
-                "typescript": "^5.1.6"
+                "typescript": "^5.6.0"
             },
             "engines": {
                 "vscode": "^1.78.0"
@@ -44,6 +44,218 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/@azure/abort-controller": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
+            "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "tslib": "^2.6.2"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/core-auth": {
+            "version": "1.9.0",
+            "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.9.0.tgz",
+            "integrity": "sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/abort-controller": "^2.0.0",
+                "@azure/core-util": "^1.11.0",
+                "tslib": "^2.6.2"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/core-client": {
+            "version": "1.9.2",
+            "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz",
+            "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/abort-controller": "^2.0.0",
+                "@azure/core-auth": "^1.4.0",
+                "@azure/core-rest-pipeline": "^1.9.1",
+                "@azure/core-tracing": "^1.0.0",
+                "@azure/core-util": "^1.6.1",
+                "@azure/logger": "^1.0.0",
+                "tslib": "^2.6.2"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/core-rest-pipeline": {
+            "version": "1.17.0",
+            "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.17.0.tgz",
+            "integrity": "sha512-62Vv8nC+uPId3j86XJ0WI+sBf0jlqTqPUFCBNrGtlaUeQUIXWV/D8GE5A1d+Qx8H7OQojn2WguC8kChD6v0shA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/abort-controller": "^2.0.0",
+                "@azure/core-auth": "^1.8.0",
+                "@azure/core-tracing": "^1.0.1",
+                "@azure/core-util": "^1.9.0",
+                "@azure/logger": "^1.0.0",
+                "http-proxy-agent": "^7.0.0",
+                "https-proxy-agent": "^7.0.0",
+                "tslib": "^2.6.2"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": {
+            "version": "7.1.1",
+            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+            "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "debug": "^4.3.4"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": {
+            "version": "7.0.2",
+            "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+            "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "agent-base": "^7.1.0",
+                "debug": "^4.3.4"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": {
+            "version": "7.0.5",
+            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+            "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "agent-base": "^7.0.2",
+                "debug": "4"
+            },
+            "engines": {
+                "node": ">= 14"
+            }
+        },
+        "node_modules/@azure/core-tracing": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.2.0.tgz",
+            "integrity": "sha512-UKTiEJPkWcESPYJz3X5uKRYyOcJD+4nYph+KpfdPRnQJVrZfk0KJgdnaAWKfhsBBtAf/D58Az4AvCJEmWgIBAg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "tslib": "^2.6.2"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/core-util": {
+            "version": "1.11.0",
+            "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.11.0.tgz",
+            "integrity": "sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/abort-controller": "^2.0.0",
+                "tslib": "^2.6.2"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/identity": {
+            "version": "4.5.0",
+            "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.5.0.tgz",
+            "integrity": "sha512-EknvVmtBuSIic47xkOqyNabAme0RYTw52BTMz8eBgU1ysTyMrD1uOoM+JdS0J/4Yfp98IBT3osqq3BfwSaNaGQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/abort-controller": "^2.0.0",
+                "@azure/core-auth": "^1.9.0",
+                "@azure/core-client": "^1.9.2",
+                "@azure/core-rest-pipeline": "^1.17.0",
+                "@azure/core-tracing": "^1.0.0",
+                "@azure/core-util": "^1.11.0",
+                "@azure/logger": "^1.0.0",
+                "@azure/msal-browser": "^3.26.1",
+                "@azure/msal-node": "^2.15.0",
+                "events": "^3.0.0",
+                "jws": "^4.0.0",
+                "open": "^8.0.0",
+                "stoppable": "^1.1.0",
+                "tslib": "^2.2.0"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/logger": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.4.tgz",
+            "integrity": "sha512-4IXXzcCdLdlXuCG+8UKEwLA1T1NHqUfanhXYHiQTn+6sfWCZXduqbtXDGceg3Ce5QxTGo7EqmbV6Bi+aqKuClQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "tslib": "^2.6.2"
+            },
+            "engines": {
+                "node": ">=18.0.0"
+            }
+        },
+        "node_modules/@azure/msal-browser": {
+            "version": "3.26.1",
+            "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.26.1.tgz",
+            "integrity": "sha512-y78sr9g61aCAH9fcLO1um+oHFXc1/5Ap88RIsUSuzkm0BHzFnN+PXGaQeuM1h5Qf5dTnWNOd6JqkskkMPAhh7Q==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/msal-common": "14.15.0"
+            },
+            "engines": {
+                "node": ">=0.8.0"
+            }
+        },
+        "node_modules/@azure/msal-common": {
+            "version": "14.15.0",
+            "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.15.0.tgz",
+            "integrity": "sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=0.8.0"
+            }
+        },
+        "node_modules/@azure/msal-node": {
+            "version": "2.15.0",
+            "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.15.0.tgz",
+            "integrity": "sha512-gVPW8YLz92ZeCibQH2QUw96odJoiM3k/ZPH3f2HxptozmH6+OnyyvKXo/Egg39HAM230akarQKHf0W74UHlh0Q==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/msal-common": "14.15.0",
+                "jsonwebtoken": "^9.0.0",
+                "uuid": "^8.3.0"
+            },
+            "engines": {
+                "node": ">=16"
+            }
+        },
         "node_modules/@esbuild/android-arm": {
             "version": "0.18.12",
             "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.12.tgz",
@@ -496,6 +708,109 @@
             "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
             "dev": true
         },
+        "node_modules/@isaacs/cliui": {
+            "version": "8.0.2",
+            "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+            "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+            "dev": true,
+            "license": "ISC",
+            "dependencies": {
+                "string-width": "^5.1.2",
+                "string-width-cjs": "npm:string-width@^4.2.0",
+                "strip-ansi": "^7.0.1",
+                "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+                "wrap-ansi": "^8.1.0",
+                "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+            },
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+            "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+            "version": "6.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+            "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+            "version": "9.2.2",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+            "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/@isaacs/cliui/node_modules/string-width": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+            "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "eastasianwidth": "^0.2.0",
+                "emoji-regex": "^9.2.2",
+                "strip-ansi": "^7.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+            "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+            "version": "8.1.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+            "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-styles": "^6.1.0",
+                "string-width": "^5.0.1",
+                "strip-ansi": "^7.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+            }
+        },
         "node_modules/@nodelib/fs.scandir": {
             "version": "2.1.5",
             "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -778,26 +1093,31 @@
             }
         },
         "node_modules/@vscode/vsce": {
-            "version": "2.19.0",
-            "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.19.0.tgz",
-            "integrity": "sha512-dAlILxC5ggOutcvJY24jxz913wimGiUrHaPkk16Gm9/PGFbz1YezWtrXsTKUtJws4fIlpX2UIlVlVESWq8lkfQ==",
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.1.1.tgz",
+            "integrity": "sha512-N62Ca9ElRPLUUzf7l9CeEBlLrYzFPRQq7huKk4pVW+LjIOSXfFIPudixn5QvZcz+yXDOh15IopI3K2o3y9666Q==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "azure-devops-node-api": "^11.0.1",
+                "@azure/identity": "^4.1.0",
+                "@vscode/vsce-sign": "^2.0.0",
+                "azure-devops-node-api": "^12.5.0",
                 "chalk": "^2.4.2",
                 "cheerio": "^1.0.0-rc.9",
-                "commander": "^6.1.0",
-                "glob": "^7.0.6",
+                "cockatiel": "^3.1.2",
+                "commander": "^6.2.1",
+                "form-data": "^4.0.0",
+                "glob": "^11.0.0",
                 "hosted-git-info": "^4.0.2",
                 "jsonc-parser": "^3.2.0",
                 "leven": "^3.1.0",
-                "markdown-it": "^12.3.2",
+                "markdown-it": "^14.1.0",
                 "mime": "^1.3.4",
                 "minimatch": "^3.0.3",
                 "parse-semver": "^1.1.1",
                 "read": "^1.0.7",
-                "semver": "^5.1.0",
-                "tmp": "^0.2.1",
+                "semver": "^7.5.2",
+                "tmp": "^0.2.3",
                 "typed-rest-client": "^1.8.4",
                 "url-join": "^4.0.1",
                 "xml2js": "^0.5.0",
@@ -808,12 +1128,157 @@
                 "vsce": "vsce"
             },
             "engines": {
-                "node": ">= 14"
+                "node": ">= 20"
             },
             "optionalDependencies": {
                 "keytar": "^7.7.0"
             }
         },
+        "node_modules/@vscode/vsce-sign": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.4.tgz",
+            "integrity": "sha512-0uL32egStKYfy60IqnynAChMTbL0oqpqk0Ew0YHiIb+fayuGZWADuIPHWUcY1GCnAA+VgchOPDMxnc2R3XGWEA==",
+            "dev": true,
+            "hasInstallScript": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optionalDependencies": {
+                "@vscode/vsce-sign-alpine-arm64": "2.0.2",
+                "@vscode/vsce-sign-alpine-x64": "2.0.2",
+                "@vscode/vsce-sign-darwin-arm64": "2.0.2",
+                "@vscode/vsce-sign-darwin-x64": "2.0.2",
+                "@vscode/vsce-sign-linux-arm": "2.0.2",
+                "@vscode/vsce-sign-linux-arm64": "2.0.2",
+                "@vscode/vsce-sign-linux-x64": "2.0.2",
+                "@vscode/vsce-sign-win32-arm64": "2.0.2",
+                "@vscode/vsce-sign-win32-x64": "2.0.2"
+            }
+        },
+        "node_modules/@vscode/vsce-sign-alpine-arm64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.2.tgz",
+            "integrity": "sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "alpine"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-alpine-x64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.2.tgz",
+            "integrity": "sha512-n1WC15MSMvTaeJ5KjWCzo0nzjydwxLyoHiMJHu1Ov0VWTZiddasmOQHekA47tFRycnt4FsQrlkSCTdgHppn6bw==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "alpine"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-darwin-arm64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.2.tgz",
+            "integrity": "sha512-rz8F4pMcxPj8fjKAJIfkUT8ycG9CjIp888VY/6pq6cuI2qEzQ0+b5p3xb74CJnBbSC0p2eRVoe+WgNCAxCLtzQ==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "darwin"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-darwin-x64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.2.tgz",
+            "integrity": "sha512-MCjPrQ5MY/QVoZ6n0D92jcRb7eYvxAujG/AH2yM6lI0BspvJQxp0o9s5oiAM9r32r9tkLpiy5s2icsbwefAQIw==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "darwin"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-linux-arm": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.2.tgz",
+            "integrity": "sha512-Fkb5jpbfhZKVw3xwR6t7WYfwKZktVGNXdg1m08uEx1anO0oUPUkoQRsNm4QniL3hmfw0ijg00YA6TrxCRkPVOQ==",
+            "cpu": [
+                "arm"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "linux"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-linux-arm64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.2.tgz",
+            "integrity": "sha512-Ybeu7cA6+/koxszsORXX0OJk9N0GgfHq70Wqi4vv2iJCZvBrOWwcIrxKjvFtwyDgdeQzgPheH5nhLVl5eQy7WA==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "linux"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-linux-x64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.2.tgz",
+            "integrity": "sha512-NsPPFVtLaTlVJKOiTnO8Cl78LZNWy0Q8iAg+LlBiCDEgC12Gt4WXOSs2pmcIjDYzj2kY4NwdeN1mBTaujYZaPg==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "linux"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-win32-arm64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.2.tgz",
+            "integrity": "sha512-wPs848ymZ3Ny+Y1Qlyi7mcT6VSigG89FWQnp2qRYCyMhdJxOpA4lDwxzlpL8fG6xC8GjQjGDkwbkWUcCobvksQ==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "win32"
+            ]
+        },
+        "node_modules/@vscode/vsce-sign-win32-x64": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.2.tgz",
+            "integrity": "sha512-pAiRN6qSAhDM5SVOIxgx+2xnoVUePHbRNC7OD2aOR3WltTKxxF25OfpK8h8UQ7A0BuRkSgREbB59DBlFk4iAeg==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "license": "SEE LICENSE IN LICENSE.txt",
+            "optional": true,
+            "os": [
+                "win32"
+            ]
+        },
         "node_modules/@vscode/vsce/node_modules/ansi-styles": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -826,6 +1291,16 @@
                 "node": ">=4"
             }
         },
+        "node_modules/@vscode/vsce/node_modules/brace-expansion": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+            "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "balanced-match": "^1.0.0"
+            }
+        },
         "node_modules/@vscode/vsce/node_modules/chalk": {
             "version": "2.4.2",
             "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -873,6 +1348,46 @@
                 "node": ">=0.8.0"
             }
         },
+        "node_modules/@vscode/vsce/node_modules/glob": {
+            "version": "11.0.0",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
+            "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
+            "dev": true,
+            "license": "ISC",
+            "dependencies": {
+                "foreground-child": "^3.1.0",
+                "jackspeak": "^4.0.1",
+                "minimatch": "^10.0.0",
+                "minipass": "^7.1.2",
+                "package-json-from-dist": "^1.0.0",
+                "path-scurry": "^2.0.0"
+            },
+            "bin": {
+                "glob": "dist/esm/bin.mjs"
+            },
+            "engines": {
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": {
+            "version": "10.0.1",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
+            "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
+            "dev": true,
+            "license": "ISC",
+            "dependencies": {
+                "brace-expansion": "^2.0.1"
+            },
+            "engines": {
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/@vscode/vsce/node_modules/has-flag": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -882,15 +1397,6 @@
                 "node": ">=4"
             }
         },
-        "node_modules/@vscode/vsce/node_modules/semver": {
-            "version": "5.7.2",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
-            "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver"
-            }
-        },
         "node_modules/@vscode/vsce/node_modules/supports-color": {
             "version": "5.5.0",
             "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@@ -903,19 +1409,6 @@
                 "node": ">=4"
             }
         },
-        "node_modules/@vscode/vsce/node_modules/xml2js": {
-            "version": "0.5.0",
-            "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
-            "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
-            "dev": true,
-            "dependencies": {
-                "sax": ">=0.6.0",
-                "xmlbuilder": "~11.0.0"
-            },
-            "engines": {
-                "node": ">=4.0.0"
-            }
-        },
         "node_modules/acorn": {
             "version": "8.10.0",
             "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
@@ -1007,11 +1500,19 @@
                 "node": ">=8"
             }
         },
+        "node_modules/asynckit": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+            "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/azure-devops-node-api": {
-            "version": "11.2.0",
-            "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz",
-            "integrity": "sha512-XdiGPhrpaT5J8wdERRKs5g8E0Zy1pvOYTli7z9E8nmOn3YGp4FhtjhrOyFmX/8veWCwdI69mCHKJw6l+4J/bHA==",
+            "version": "12.5.0",
+            "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz",
+            "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "tunnel": "0.0.6",
                 "typed-rest-client": "^1.8.4"
@@ -1132,14 +1633,28 @@
                 "node": "*"
             }
         },
+        "node_modules/buffer-equal-constant-time": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+            "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+            "dev": true,
+            "license": "BSD-3-Clause"
+        },
         "node_modules/call-bind": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-            "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+            "version": "1.0.7",
+            "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+            "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "function-bind": "^1.1.1",
-                "get-intrinsic": "^1.0.2"
+                "es-define-property": "^1.0.0",
+                "es-errors": "^1.3.0",
+                "function-bind": "^1.1.2",
+                "get-intrinsic": "^1.2.4",
+                "set-function-length": "^1.2.1"
+            },
+            "engines": {
+                "node": ">= 0.4"
             },
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
@@ -1234,6 +1749,16 @@
                 "node": ">=12"
             }
         },
+        "node_modules/cockatiel": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz",
+            "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=16"
+            }
+        },
         "node_modules/color-convert": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1250,6 +1775,19 @@
             "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
             "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
         },
+        "node_modules/combined-stream": {
+            "version": "1.0.8",
+            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+            "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "delayed-stream": "~1.0.0"
+            },
+            "engines": {
+                "node": ">= 0.8"
+            }
+        },
         "node_modules/commander": {
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
@@ -1780,6 +2318,34 @@
             "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
             "dev": true
         },
+        "node_modules/define-data-property": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+            "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "es-define-property": "^1.0.0",
+                "es-errors": "^1.3.0",
+                "gopd": "^1.0.1"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
+        "node_modules/define-lazy-prop": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+            "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/delaunator": {
             "version": "5.0.0",
             "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
@@ -1788,6 +2354,16 @@
                 "robust-predicates": "^3.0.0"
             }
         },
+        "node_modules/delayed-stream": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+            "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=0.4.0"
+            }
+        },
         "node_modules/detect-libc": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
@@ -1877,6 +2453,23 @@
                 "url": "https://github.com/fb55/domutils?sponsor=1"
             }
         },
+        "node_modules/eastasianwidth": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+            "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/ecdsa-sig-formatter": {
+            "version": "1.0.11",
+            "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+            "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+            "dev": true,
+            "license": "Apache-2.0",
+            "dependencies": {
+                "safe-buffer": "^5.0.1"
+            }
+        },
         "node_modules/emoji-regex": {
             "version": "8.0.0",
             "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -1904,6 +2497,29 @@
                 "url": "https://github.com/fb55/entities?sponsor=1"
             }
         },
+        "node_modules/es-define-property": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+            "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "get-intrinsic": "^1.2.4"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
+        "node_modules/es-errors": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+            "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
         "node_modules/esbuild": {
             "version": "0.18.12",
             "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.12.tgz",
@@ -2156,6 +2772,16 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/events": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+            "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=0.8.x"
+            }
+        },
         "node_modules/expand-template": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -2309,6 +2935,38 @@
                 }
             }
         },
+        "node_modules/foreground-child": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+            "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+            "dev": true,
+            "license": "ISC",
+            "dependencies": {
+                "cross-spawn": "^7.0.0",
+                "signal-exit": "^4.0.1"
+            },
+            "engines": {
+                "node": ">=14"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/form-data": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+            "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "asynckit": "^0.4.0",
+                "combined-stream": "^1.0.8",
+                "mime-types": "^2.1.12"
+            },
+            "engines": {
+                "node": ">= 6"
+            }
+        },
         "node_modules/fs-constants": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
@@ -2323,10 +2981,14 @@
             "dev": true
         },
         "node_modules/function-bind": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-            "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-            "dev": true
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+            "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+            "dev": true,
+            "license": "MIT",
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
         },
         "node_modules/get-caller-file": {
             "version": "2.0.5",
@@ -2337,14 +2999,20 @@
             }
         },
         "node_modules/get-intrinsic": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
-            "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+            "version": "1.2.4",
+            "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+            "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "function-bind": "^1.1.1",
-                "has": "^1.0.3",
-                "has-symbols": "^1.0.3"
+                "es-errors": "^1.3.0",
+                "function-bind": "^1.1.2",
+                "has-proto": "^1.0.1",
+                "has-symbols": "^1.0.3",
+                "hasown": "^2.0.0"
+            },
+            "engines": {
+                "node": ">= 0.4"
             },
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
@@ -2424,6 +3092,19 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/gopd": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+            "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "get-intrinsic": "^1.1.3"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
         "node_modules/grapheme-splitter": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
@@ -2436,18 +3117,6 @@
             "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
             "dev": true
         },
-        "node_modules/has": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-            "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-            "dev": true,
-            "dependencies": {
-                "function-bind": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
         "node_modules/has-flag": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -2457,11 +3126,38 @@
                 "node": ">=8"
             }
         },
+        "node_modules/has-property-descriptors": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+            "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "es-define-property": "^1.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
+        "node_modules/has-proto": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+            "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
         "node_modules/has-symbols": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
             "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">= 0.4"
             },
@@ -2469,6 +3165,19 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/hasown": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+            "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "function-bind": "^1.1.2"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
         "node_modules/hosted-git-info": {
             "version": "4.1.0",
             "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
@@ -2642,6 +3351,22 @@
                 "is-ci": "bin.js"
             }
         },
+        "node_modules/is-docker": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+            "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+            "dev": true,
+            "license": "MIT",
+            "bin": {
+                "is-docker": "cli.js"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/is-extglob": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2689,6 +3414,19 @@
                 "node": ">=8"
             }
         },
+        "node_modules/is-wsl": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+            "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "is-docker": "^2.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/isarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -2701,6 +3439,22 @@
             "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
             "dev": true
         },
+        "node_modules/jackspeak": {
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
+            "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
+            "dev": true,
+            "license": "BlueOak-1.0.0",
+            "dependencies": {
+                "@isaacs/cliui": "^8.0.2"
+            },
+            "engines": {
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/js-yaml": {
             "version": "4.1.0",
             "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -2731,6 +3485,52 @@
             "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
             "dev": true
         },
+        "node_modules/jsonwebtoken": {
+            "version": "9.0.2",
+            "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
+            "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "jws": "^3.2.2",
+                "lodash.includes": "^4.3.0",
+                "lodash.isboolean": "^3.0.3",
+                "lodash.isinteger": "^4.0.4",
+                "lodash.isnumber": "^3.0.3",
+                "lodash.isplainobject": "^4.0.6",
+                "lodash.isstring": "^4.0.1",
+                "lodash.once": "^4.0.0",
+                "ms": "^2.1.1",
+                "semver": "^7.5.4"
+            },
+            "engines": {
+                "node": ">=12",
+                "npm": ">=6"
+            }
+        },
+        "node_modules/jsonwebtoken/node_modules/jwa": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+            "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "buffer-equal-constant-time": "1.0.1",
+                "ecdsa-sig-formatter": "1.0.11",
+                "safe-buffer": "^5.0.1"
+            }
+        },
+        "node_modules/jsonwebtoken/node_modules/jws": {
+            "version": "3.2.2",
+            "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+            "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "jwa": "^1.4.1",
+                "safe-buffer": "^5.0.1"
+            }
+        },
         "node_modules/jszip": {
             "version": "3.10.1",
             "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
@@ -2743,6 +3543,29 @@
                 "setimmediate": "^1.0.5"
             }
         },
+        "node_modules/jwa": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
+            "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "buffer-equal-constant-time": "1.0.1",
+                "ecdsa-sig-formatter": "1.0.11",
+                "safe-buffer": "^5.0.1"
+            }
+        },
+        "node_modules/jws": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
+            "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "jwa": "^2.0.0",
+                "safe-buffer": "^5.0.1"
+            }
+        },
         "node_modules/keytar": {
             "version": "7.9.0",
             "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz",
@@ -2787,12 +3610,13 @@
             }
         },
         "node_modules/linkify-it": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
-            "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+            "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "uc.micro": "^1.0.1"
+                "uc.micro": "^2.0.0"
             }
         },
         "node_modules/locate-path": {
@@ -2810,12 +3634,61 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/lodash.includes": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+            "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/lodash.isboolean": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+            "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/lodash.isinteger": {
+            "version": "4.0.4",
+            "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+            "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/lodash.isnumber": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+            "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/lodash.isplainobject": {
+            "version": "4.0.6",
+            "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+            "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/lodash.isstring": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+            "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/lodash.merge": {
             "version": "4.6.2",
             "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
             "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
             "dev": true
         },
+        "node_modules/lodash.once": {
+            "version": "4.1.1",
+            "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+            "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/lru-cache": {
             "version": "6.0.0",
             "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -2828,35 +3701,29 @@
             }
         },
         "node_modules/markdown-it": {
-            "version": "12.3.2",
-            "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
-            "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
+            "version": "14.1.0",
+            "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
+            "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "argparse": "^2.0.1",
-                "entities": "~2.1.0",
-                "linkify-it": "^3.0.1",
-                "mdurl": "^1.0.1",
-                "uc.micro": "^1.0.5"
+                "entities": "^4.4.0",
+                "linkify-it": "^5.0.0",
+                "mdurl": "^2.0.0",
+                "punycode.js": "^2.3.1",
+                "uc.micro": "^2.1.0"
             },
             "bin": {
-                "markdown-it": "bin/markdown-it.js"
-            }
-        },
-        "node_modules/markdown-it/node_modules/entities": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
-            "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
-            "dev": true,
-            "funding": {
-                "url": "https://github.com/fb55/entities?sponsor=1"
+                "markdown-it": "bin/markdown-it.mjs"
             }
         },
         "node_modules/mdurl": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
-            "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
-            "dev": true
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+            "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/merge2": {
             "version": "1.4.1",
@@ -2868,12 +3735,13 @@
             }
         },
         "node_modules/micromatch": {
-            "version": "4.0.5",
-            "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-            "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+            "version": "4.0.8",
+            "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+            "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "braces": "^3.0.2",
+                "braces": "^3.0.3",
                 "picomatch": "^2.3.1"
             },
             "engines": {
@@ -2892,6 +3760,29 @@
                 "node": ">=4"
             }
         },
+        "node_modules/mime-db": {
+            "version": "1.52.0",
+            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+            "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">= 0.6"
+            }
+        },
+        "node_modules/mime-types": {
+            "version": "2.1.35",
+            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+            "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "mime-db": "1.52.0"
+            },
+            "engines": {
+                "node": ">= 0.6"
+            }
+        },
         "node_modules/mimic-response": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
@@ -2927,6 +3818,16 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/minipass": {
+            "version": "7.1.2",
+            "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+            "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+            "dev": true,
+            "license": "ISC",
+            "engines": {
+                "node": ">=16 || 14 >=14.17"
+            }
+        },
         "node_modules/mkdirp-classic": {
             "version": "0.5.3",
             "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
@@ -2998,10 +3899,14 @@
             }
         },
         "node_modules/object-inspect": {
-            "version": "1.12.3",
-            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
-            "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+            "version": "1.13.2",
+            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
+            "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
             "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">= 0.4"
+            },
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
             }
@@ -3015,6 +3920,24 @@
                 "wrappy": "1"
             }
         },
+        "node_modules/open": {
+            "version": "8.4.2",
+            "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+            "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "define-lazy-prop": "^2.0.0",
+                "is-docker": "^2.1.1",
+                "is-wsl": "^2.2.0"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/optionator": {
             "version": "0.9.3",
             "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
@@ -3053,6 +3976,93 @@
                 "node": ">= 14"
             }
         },
+        "node_modules/ovsx/node_modules/@vscode/vsce": {
+            "version": "2.32.0",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.32.0.tgz",
+            "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@azure/identity": "^4.1.0",
+                "@vscode/vsce-sign": "^2.0.0",
+                "azure-devops-node-api": "^12.5.0",
+                "chalk": "^2.4.2",
+                "cheerio": "^1.0.0-rc.9",
+                "cockatiel": "^3.1.2",
+                "commander": "^6.2.1",
+                "form-data": "^4.0.0",
+                "glob": "^7.0.6",
+                "hosted-git-info": "^4.0.2",
+                "jsonc-parser": "^3.2.0",
+                "leven": "^3.1.0",
+                "markdown-it": "^12.3.2",
+                "mime": "^1.3.4",
+                "minimatch": "^3.0.3",
+                "parse-semver": "^1.1.1",
+                "read": "^1.0.7",
+                "semver": "^7.5.2",
+                "tmp": "^0.2.1",
+                "typed-rest-client": "^1.8.4",
+                "url-join": "^4.0.1",
+                "xml2js": "^0.5.0",
+                "yauzl": "^2.3.1",
+                "yazl": "^2.2.2"
+            },
+            "bin": {
+                "vsce": "vsce"
+            },
+            "engines": {
+                "node": ">= 16"
+            },
+            "optionalDependencies": {
+                "keytar": "^7.7.0"
+            }
+        },
+        "node_modules/ovsx/node_modules/ansi-styles": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+            "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "color-convert": "^1.9.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/ovsx/node_modules/chalk": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/ovsx/node_modules/color-convert": {
+            "version": "1.9.3",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "color-name": "1.1.3"
+            }
+        },
+        "node_modules/ovsx/node_modules/color-name": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/ovsx/node_modules/commander": {
             "version": "6.2.1",
             "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
@@ -3062,6 +4072,90 @@
                 "node": ">= 6"
             }
         },
+        "node_modules/ovsx/node_modules/entities": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
+            "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
+            "dev": true,
+            "license": "BSD-2-Clause",
+            "funding": {
+                "url": "https://github.com/fb55/entities?sponsor=1"
+            }
+        },
+        "node_modules/ovsx/node_modules/escape-string-regexp": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=0.8.0"
+            }
+        },
+        "node_modules/ovsx/node_modules/has-flag": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/ovsx/node_modules/linkify-it": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
+            "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "uc.micro": "^1.0.1"
+            }
+        },
+        "node_modules/ovsx/node_modules/markdown-it": {
+            "version": "12.3.2",
+            "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
+            "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "argparse": "^2.0.1",
+                "entities": "~2.1.0",
+                "linkify-it": "^3.0.1",
+                "mdurl": "^1.0.1",
+                "uc.micro": "^1.0.5"
+            },
+            "bin": {
+                "markdown-it": "bin/markdown-it.js"
+            }
+        },
+        "node_modules/ovsx/node_modules/mdurl": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+            "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/ovsx/node_modules/supports-color": {
+            "version": "5.5.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "has-flag": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=4"
+            }
+        },
+        "node_modules/ovsx/node_modules/uc.micro": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+            "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/p-limit": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -3092,6 +4186,13 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/package-json-from-dist": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+            "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+            "dev": true,
+            "license": "BlueOak-1.0.0"
+        },
         "node_modules/pako": {
             "version": "1.0.11",
             "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -3180,6 +4281,33 @@
                 "node": ">=8"
             }
         },
+        "node_modules/path-scurry": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+            "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
+            "dev": true,
+            "license": "BlueOak-1.0.0",
+            "dependencies": {
+                "lru-cache": "^11.0.0",
+                "minipass": "^7.1.2"
+            },
+            "engines": {
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/path-scurry/node_modules/lru-cache": {
+            "version": "11.0.1",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz",
+            "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==",
+            "dev": true,
+            "license": "ISC",
+            "engines": {
+                "node": "20 || >=22"
+            }
+        },
         "node_modules/path-type": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -3284,13 +4412,24 @@
                 "node": ">=6"
             }
         },
+        "node_modules/punycode.js": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+            "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=6"
+            }
+        },
         "node_modules/qs": {
-            "version": "6.11.0",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
-            "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+            "version": "6.13.0",
+            "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+            "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
             "dev": true,
+            "license": "BSD-3-Clause",
             "dependencies": {
-                "side-channel": "^1.0.4"
+                "side-channel": "^1.0.6"
             },
             "engines": {
                 "node": ">=0.6"
@@ -3478,6 +4617,24 @@
                 "node": ">=10"
             }
         },
+        "node_modules/set-function-length": {
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+            "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "define-data-property": "^1.1.4",
+                "es-errors": "^1.3.0",
+                "function-bind": "^1.1.2",
+                "get-intrinsic": "^1.2.4",
+                "gopd": "^1.0.1",
+                "has-property-descriptors": "^1.0.2"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
         "node_modules/setimmediate": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
@@ -3506,19 +4663,37 @@
             }
         },
         "node_modules/side-channel": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-            "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+            "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "call-bind": "^1.0.0",
-                "get-intrinsic": "^1.0.2",
-                "object-inspect": "^1.9.0"
+                "call-bind": "^1.0.7",
+                "es-errors": "^1.3.0",
+                "get-intrinsic": "^1.2.4",
+                "object-inspect": "^1.13.1"
+            },
+            "engines": {
+                "node": ">= 0.4"
             },
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/signal-exit": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+            "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+            "dev": true,
+            "license": "ISC",
+            "engines": {
+                "node": ">=14"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/simple-concat": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
@@ -3575,6 +4750,17 @@
                 "node": ">=8"
             }
         },
+        "node_modules/stoppable": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz",
+            "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=4",
+                "npm": ">=6"
+            }
+        },
         "node_modules/string_decoder": {
             "version": "1.1.1",
             "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -3597,6 +4783,22 @@
                 "node": ">=8"
             }
         },
+        "node_modules/string-width-cjs": {
+            "name": "string-width",
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/strip-ansi": {
             "version": "6.0.1",
             "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -3608,6 +4810,20 @@
                 "node": ">=8"
             }
         },
+        "node_modules/strip-ansi-cjs": {
+            "name": "strip-ansi",
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/strip-json-comments": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -3684,15 +4900,13 @@
             "dev": true
         },
         "node_modules/tmp": {
-            "version": "0.2.1",
-            "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
-            "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+            "version": "0.2.3",
+            "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
+            "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
             "dev": true,
-            "dependencies": {
-                "rimraf": "^3.0.0"
-            },
+            "license": "MIT",
             "engines": {
-                "node": ">=8.17.0"
+                "node": ">=14.14"
             }
         },
         "node_modules/to-regex-range": {
@@ -3720,16 +4934,18 @@
             }
         },
         "node_modules/tslib": {
-            "version": "2.6.0",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
-            "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==",
-            "dev": true
+            "version": "2.8.0",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
+            "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
+            "dev": true,
+            "license": "0BSD"
         },
         "node_modules/tunnel": {
             "version": "0.0.6",
             "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
             "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
             }
@@ -3772,10 +4988,11 @@
             }
         },
         "node_modules/typed-rest-client": {
-            "version": "1.8.9",
-            "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.9.tgz",
-            "integrity": "sha512-uSmjE38B80wjL85UFX3sTYEUlvZ1JgCRhsWj/fJ4rZ0FqDUFoIuodtiVeE+cUqiVTOKPdKrp/sdftD15MDek6g==",
+            "version": "1.8.11",
+            "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz",
+            "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "qs": "^6.9.1",
                 "tunnel": "0.0.6",
@@ -3783,10 +5000,11 @@
             }
         },
         "node_modules/typescript": {
-            "version": "5.1.6",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
-            "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+            "version": "5.6.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
+            "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
             "dev": true,
+            "license": "Apache-2.0",
             "bin": {
                 "tsc": "bin/tsc",
                 "tsserver": "bin/tsserver"
@@ -3796,16 +5014,18 @@
             }
         },
         "node_modules/uc.micro": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
-            "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
-            "dev": true
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+            "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/underscore": {
-            "version": "1.13.6",
-            "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
-            "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
-            "dev": true
+            "version": "1.13.7",
+            "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz",
+            "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/uri-js": {
             "version": "4.4.1",
@@ -3828,6 +5048,16 @@
             "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
             "dev": true
         },
+        "node_modules/uuid": {
+            "version": "8.3.2",
+            "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+            "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+            "dev": true,
+            "license": "MIT",
+            "bin": {
+                "uuid": "dist/bin/uuid"
+            }
+        },
         "node_modules/vscode-jsonrpc": {
             "version": "8.1.0",
             "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.1.0.tgz",
@@ -3913,12 +5143,45 @@
                 "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
             }
         },
+        "node_modules/wrap-ansi-cjs": {
+            "name": "wrap-ansi",
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+            "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+            }
+        },
         "node_modules/wrappy": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
             "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
             "dev": true
         },
+        "node_modules/xml2js": {
+            "version": "0.5.0",
+            "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+            "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "sax": ">=0.6.0",
+                "xmlbuilder": "~11.0.0"
+            },
+            "engines": {
+                "node": ">=4.0.0"
+            }
+        },
         "node_modules/xmlbuilder": {
             "version": "11.0.1",
             "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index a52b3d1ec5c..e55eceff781 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -58,14 +58,14 @@
         "@typescript-eslint/eslint-plugin": "^6.0.0",
         "@typescript-eslint/parser": "^6.0.0",
         "@vscode/test-electron": "^2.3.8",
-        "@vscode/vsce": "^2.19.0",
+        "@vscode/vsce": "^3.0.0",
         "esbuild": "^0.18.12",
         "eslint": "^8.44.0",
         "eslint-config-prettier": "^8.8.0",
         "ovsx": "^0.8.2",
         "prettier": "^3.0.0",
         "tslib": "^2.6.0",
-        "typescript": "^5.1.6"
+        "typescript": "^5.6.0"
     },
     "activationEvents": [
         "workspaceContains:Cargo.toml",
@@ -349,6 +349,11 @@
                         "markdownDescription": "Whether to show the test explorer.",
                         "default": false,
                         "type": "boolean"
+                    },
+                    "rust-analyzer.initializeStopped": {
+                        "markdownDescription": "Do not start rust-analyzer server when the extension is activated.",
+                        "default": false,
+                        "type": "boolean"
                     }
                 }
             },
@@ -728,8 +733,8 @@
                     "rust-analyzer.cargo.cfgs": {
                         "markdownDescription": "List of cfg options to enable with the given values.",
                         "default": {
-                            "debug_assertions": null,
-                            "miri": null
+                            "miri": null,
+                            "debug_assertions": null
                         },
                         "type": "object"
                     }
@@ -1152,18 +1157,10 @@
                     "rust-analyzer.completion.snippets.custom": {
                         "markdownDescription": "Custom completion snippets.",
                         "default": {
-                            "Arc::new": {
-                                "postfix": "arc",
-                                "body": "Arc::new(${receiver})",
-                                "requires": "std::sync::Arc",
-                                "description": "Put the expression into an `Arc`",
-                                "scope": "expr"
-                            },
-                            "Rc::new": {
-                                "postfix": "rc",
-                                "body": "Rc::new(${receiver})",
-                                "requires": "std::rc::Rc",
-                                "description": "Put the expression into an `Rc`",
+                            "Ok": {
+                                "postfix": "ok",
+                                "body": "Ok(${receiver})",
+                                "description": "Wrap the expression in a `Result::Ok`",
                                 "scope": "expr"
                             },
                             "Box::pin": {
@@ -1173,10 +1170,11 @@
                                 "description": "Put the expression into a pinned `Box`",
                                 "scope": "expr"
                             },
-                            "Err": {
-                                "postfix": "err",
-                                "body": "Err(${receiver})",
-                                "description": "Wrap the expression in a `Result::Err`",
+                            "Arc::new": {
+                                "postfix": "arc",
+                                "body": "Arc::new(${receiver})",
+                                "requires": "std::sync::Arc",
+                                "description": "Put the expression into an `Arc`",
                                 "scope": "expr"
                             },
                             "Some": {
@@ -1185,10 +1183,17 @@
                                 "description": "Wrap the expression in an `Option::Some`",
                                 "scope": "expr"
                             },
-                            "Ok": {
-                                "postfix": "ok",
-                                "body": "Ok(${receiver})",
-                                "description": "Wrap the expression in a `Result::Ok`",
+                            "Err": {
+                                "postfix": "err",
+                                "body": "Err(${receiver})",
+                                "description": "Wrap the expression in a `Result::Err`",
+                                "scope": "expr"
+                            },
+                            "Rc::new": {
+                                "postfix": "rc",
+                                "body": "Rc::new(${receiver})",
+                                "requires": "std::rc::Rc",
+                                "description": "Put the expression into an `Rc`",
                                 "scope": "expr"
                             }
                         },
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index abb4099f9f5..67bc72f1e12 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -330,6 +330,10 @@ export class Config {
     get statusBarClickAction() {
         return this.get<string>("statusBar.clickAction");
     }
+
+    get initializeStopped() {
+        return this.get<boolean>("initializeStopped");
+    }
 }
 
 export function prepareVSCodeConfig<T>(resp: T): T {
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index 77ab44f24ce..9e2e3d2185b 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -6,7 +6,6 @@ import type * as ra from "./lsp_ext";
 import { Cargo } from "./toolchain";
 import type { Ctx } from "./ctx";
 import { createTaskFromRunnable, prepareEnv } from "./run";
-import { execSync } from "node:child_process";
 import { execute, isCargoRunnableArgs, unwrapUndefinable } from "./util";
 import type { Config } from "./config";
 
@@ -152,9 +151,24 @@ async function getDebugConfiguration(
     const env = prepareEnv(inheritEnv, runnable.label, runnableArgs, config.runnablesExtraEnv);
     const executable = await getDebugExecutable(runnableArgs, env);
     let sourceFileMap = debugOptions.sourceFileMap;
+
     if (sourceFileMap === "auto") {
         sourceFileMap = {};
-        await discoverSourceFileMap(sourceFileMap, env, wsFolder);
+        const computedSourceFileMap = await discoverSourceFileMap(env, wsFolder);
+
+        if (computedSourceFileMap) {
+            // lldb-dap requires passing the source map as an array of two element arrays.
+            // the two element array contains a source and destination pathname.
+            // TODO: remove lldb-dap-specific post-processing once
+            // https://github.com/llvm/llvm-project/pull/106919/ is released in the extension.
+            if (provider.type === "lldb-dap") {
+                provider.additional["sourceMap"] = [
+                    [computedSourceFileMap?.source, computedSourceFileMap?.destination],
+                ];
+            } else {
+                sourceFileMap[computedSourceFileMap.source] = computedSourceFileMap.destination;
+            }
+        }
     }
 
     const debugConfig = getDebugConfig(
@@ -189,11 +203,15 @@ async function getDebugConfiguration(
     return debugConfig;
 }
 
+type SourceFileMap = {
+    source: string;
+    destination: string;
+};
+
 async function discoverSourceFileMap(
-    sourceFileMap: Record<string, string>,
     env: Record<string, string>,
     cwd: string,
-) {
+): Promise<SourceFileMap | undefined> {
     const sysroot = env["RUSTC_TOOLCHAIN"];
     if (sysroot) {
         // let's try to use the default toolchain
@@ -203,9 +221,11 @@ async function discoverSourceFileMap(
         const commitHash = rx.exec(data)?.[1];
         if (commitHash) {
             const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
-            sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
+            return { source: rustlib, destination: rustlib };
         }
     }
+
+    return;
 }
 
 type PropertyFetcher<Config, Input, Key extends keyof Config> = (
@@ -218,7 +238,7 @@ type DebugConfigProvider<Type extends string, DebugConfig extends BaseDebugConfi
     runnableArgsProperty: PropertyFetcher<DebugConfig, ra.CargoRunnableArgs, keyof DebugConfig>;
     sourceFileMapProperty?: keyof DebugConfig;
     type: Type;
-    additional?: Record<string, unknown>;
+    additional: Record<string, unknown>;
 };
 
 type KnownEnginesType = (typeof knownEngines)[keyof typeof knownEngines];
@@ -236,16 +256,7 @@ const knownEngines: {
             "args",
             runnableArgs.executableArgs,
         ],
-        additional: {
-            sourceMap: [
-                [
-                    `/rustc/${/commit-hash:\s(.*)$/m.exec(
-                        execSync("rustc -V -v", {}).toString(),
-                    )?.[1]}/library`,
-                    "${config:rust-analyzer.cargo.sysroot}/lib/rustlib/src/rust/library",
-                ],
-            ],
-        },
+        additional: {},
     },
     "vadimcn.vscode-lldb": {
         type: "lldb",
diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts
index 0ddc5619e99..fdf43f66f94 100644
--- a/src/tools/rust-analyzer/editors/code/src/main.ts
+++ b/src/tools/rust-analyzer/editors/code/src/main.ts
@@ -107,7 +107,14 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
         initializeDebugSessionTrackingAndRebuild(ctx);
     }
 
-    await ctx.start();
+    if (ctx.config.initializeStopped) {
+        ctx.setServerStatus({
+            health: "stopped",
+        });
+    } else {
+        await ctx.start();
+    }
+
     return ctx;
 }
 
diff --git a/src/tools/rust-analyzer/lib/line-index/Cargo.toml b/src/tools/rust-analyzer/lib/line-index/Cargo.toml
index 8ae4954dd0d..14196ba3d09 100644
--- a/src/tools/rust-analyzer/lib/line-index/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/line-index/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "line-index"
-version = "0.1.1"
+version = "0.1.2"
 description = "Maps flat `TextSize` offsets to/from `(line, column)` representation."
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/line-index"
diff --git a/src/tools/rust-analyzer/lib/line-index/src/lib.rs b/src/tools/rust-analyzer/lib/line-index/src/lib.rs
index 66875e25242..6f0455ee98b 100644
--- a/src/tools/rust-analyzer/lib/line-index/src/lib.rs
+++ b/src/tools/rust-analyzer/lib/line-index/src/lib.rs
@@ -177,6 +177,14 @@ impl LineIndex {
         Some(LineCol { line: line_col.line, col })
     }
 
+    /// Returns the given line's range.
+    pub fn line(&self, line: u32) -> Option<TextRange> {
+        let start = self.start_offset(line as usize)?;
+        let next_newline = self.newlines.get(line as usize).copied().unwrap_or(self.len);
+        let line_length = next_newline - start;
+        Some(TextRange::new(start, start + line_length))
+    }
+
     /// Given a range [start, end), returns a sorted iterator of non-empty ranges [start, x1), [x1,
     /// x2), ..., [xn, end) where all the xi, which are positions of newlines, are inside the range
     /// [start, end).
diff --git a/src/tools/rust-analyzer/lib/line-index/src/tests.rs b/src/tools/rust-analyzer/lib/line-index/src/tests.rs
index 57fad1dfc05..f2bb04aec32 100644
--- a/src/tools/rust-analyzer/lib/line-index/src/tests.rs
+++ b/src/tools/rust-analyzer/lib/line-index/src/tests.rs
@@ -195,3 +195,26 @@ fn test_every_chars() {
         }
     }
 }
+
+#[test]
+fn test_line() {
+    use text_size::TextRange;
+
+    macro_rules! validate {
+        ($text:expr, $line:expr, $expected_start:literal .. $expected_end:literal) => {
+            let line_index = LineIndex::new($text);
+            assert_eq!(
+                line_index.line($line),
+                Some(TextRange::new(
+                    TextSize::from($expected_start),
+                    TextSize::from($expected_end)
+                ))
+            );
+        };
+    }
+
+    validate!("", 0, 0..0);
+    validate!("\n", 1, 1..1);
+    validate!("\nabc", 1, 1..4);
+    validate!("\nabc\ndef", 1, 1..5);
+}
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index d0f9fa7ac42..bc324402a96 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-dd5127615ad626741a1116d022cf784637ac05df
+1de57a5ce952c722f7053aeacfc6c90bc139b678
diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs
index f1a96e0c6a2..9269d154235 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs
@@ -111,7 +111,7 @@ const RESERVED: &[&str] = &[
 // keywords that are keywords only in specific parse contexts
 #[doc(alias = "WEAK_KEYWORDS")]
 const CONTEXTUAL_KEYWORDS: &[&str] =
-    &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet"];
+    &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet", "safe"];
 // keywords we use for special macro expansions
 const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[
     "asm",