diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs
index 40e801d03885c..f71e6f3e6f3a6 100644
--- a/compiler/rustc_borrowck/src/polonius/dump.rs
+++ b/compiler/rustc_borrowck/src/polonius/dump.rs
@@ -1,14 +1,18 @@
 use std::io;
 
+use rustc_data_structures::fx::FxHashSet;
+use rustc_index::IndexVec;
 use rustc_middle::mir::pretty::{
     PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer,
 };
 use rustc_middle::mir::{Body, ClosureRegionRequirements};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_session::config::MirIncludeSpans;
 
 use crate::borrow_set::BorrowSet;
+use crate::constraints::OutlivesConstraint;
 use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet};
+use crate::type_check::Locations;
 use crate::{BorrowckInferCtxt, RegionInferenceContext};
 
 /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
@@ -50,6 +54,8 @@ pub(crate) fn dump_polonius_mir<'tcx>(
 /// - the NLL MIR
 /// - the list of polonius localized constraints
 /// - a mermaid graph of the CFG
+/// - a mermaid graph of the NLL regions and the constraints between them
+/// - a mermaid graph of the NLL SCCs and the constraints between them
 fn emit_polonius_dump<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
@@ -68,7 +74,7 @@ fn emit_polonius_dump<'tcx>(
     // Section 1: the NLL + Polonius MIR.
     writeln!(out, "<div>")?;
     writeln!(out, "Raw MIR dump")?;
-    writeln!(out, "<code><pre>")?;
+    writeln!(out, "<pre><code>")?;
     emit_html_mir(
         tcx,
         body,
@@ -78,15 +84,31 @@ fn emit_polonius_dump<'tcx>(
         closure_region_requirements,
         out,
     )?;
-    writeln!(out, "</pre></code>")?;
+    writeln!(out, "</code></pre>")?;
     writeln!(out, "</div>")?;
 
     // Section 2: mermaid visualization of the CFG.
     writeln!(out, "<div>")?;
     writeln!(out, "Control-flow graph")?;
-    writeln!(out, "<code><pre class='mermaid'>")?;
+    writeln!(out, "<pre class='mermaid'>")?;
     emit_mermaid_cfg(body, out)?;
-    writeln!(out, "</pre></code>")?;
+    writeln!(out, "</pre>")?;
+    writeln!(out, "</div>")?;
+
+    // Section 3: mermaid visualization of the NLL region graph.
+    writeln!(out, "<div>")?;
+    writeln!(out, "NLL regions")?;
+    writeln!(out, "<pre class='mermaid'>")?;
+    emit_mermaid_nll_regions(regioncx, out)?;
+    writeln!(out, "</pre>")?;
+    writeln!(out, "</div>")?;
+
+    // Section 4: mermaid visualization of the NLL SCC graph.
+    writeln!(out, "<div>")?;
+    writeln!(out, "NLL SCCs")?;
+    writeln!(out, "<pre class='mermaid'>")?;
+    emit_mermaid_nll_sccs(regioncx, out)?;
+    writeln!(out, "</pre>")?;
     writeln!(out, "</div>")?;
 
     // Finalize the dump with the HTML epilogue.
@@ -261,3 +283,112 @@ fn emit_mermaid_cfg(body: &Body<'_>, out: &mut dyn io::Write) -> io::Result<()>
 
     Ok(())
 }
+
+/// Emits a region's label: index, universe, external name.
+fn render_region(
+    region: RegionVid,
+    regioncx: &RegionInferenceContext<'_>,
+    out: &mut dyn io::Write,
+) -> io::Result<()> {
+    let def = regioncx.region_definition(region);
+    let universe = def.universe;
+
+    write!(out, "'{}", region.as_usize())?;
+    if !universe.is_root() {
+        write!(out, "/{universe:?}")?;
+    }
+    if let Some(name) = def.external_name.and_then(|e| e.get_name()) {
+        write!(out, " ({name})")?;
+    }
+    Ok(())
+}
+
+/// Emits a mermaid flowchart of the NLL regions and the outlives constraints between them, similar
+/// to the graphviz version.
+fn emit_mermaid_nll_regions<'tcx>(
+    regioncx: &RegionInferenceContext<'tcx>,
+    out: &mut dyn io::Write,
+) -> io::Result<()> {
+    // The mermaid chart type: a top-down flowchart.
+    writeln!(out, "flowchart TD")?;
+
+    // Emit the region nodes.
+    for region in regioncx.var_infos.indices() {
+        write!(out, "{}[\"", region.as_usize())?;
+        render_region(region, regioncx, out)?;
+        writeln!(out, "\"]")?;
+    }
+
+    // Get a set of edges to check for the reverse edge being present.
+    let edges: FxHashSet<_> = regioncx.outlives_constraints().map(|c| (c.sup, c.sub)).collect();
+
+    // Order (and deduplicate) edges for traversal, to display them in a generally increasing order.
+    let constraint_key = |c: &OutlivesConstraint<'_>| {
+        let min = c.sup.min(c.sub);
+        let max = c.sup.max(c.sub);
+        (min, max)
+    };
+    let mut ordered_edges: Vec<_> = regioncx.outlives_constraints().collect();
+    ordered_edges.sort_by_key(|c| constraint_key(c));
+    ordered_edges.dedup_by_key(|c| constraint_key(c));
+
+    for outlives in ordered_edges {
+        // Source node.
+        write!(out, "{} ", outlives.sup.as_usize())?;
+
+        // The kind of arrow: bidirectional if the opposite edge exists in the set.
+        if edges.contains(&(outlives.sub, outlives.sup)) {
+            write!(out, "&lt;")?;
+        }
+        write!(out, "-- ")?;
+
+        // Edge label from its `Locations`.
+        match outlives.locations {
+            Locations::All(_) => write!(out, "All")?,
+            Locations::Single(location) => write!(out, "{:?}", location)?,
+        }
+
+        // Target node.
+        writeln!(out, " --> {}", outlives.sub.as_usize())?;
+    }
+    Ok(())
+}
+
+/// Emits a mermaid flowchart of the NLL SCCs and the outlives constraints between them, similar
+/// to the graphviz version.
+fn emit_mermaid_nll_sccs<'tcx>(
+    regioncx: &RegionInferenceContext<'tcx>,
+    out: &mut dyn io::Write,
+) -> io::Result<()> {
+    // The mermaid chart type: a top-down flowchart.
+    writeln!(out, "flowchart TD")?;
+
+    // Gather and emit the SCC nodes.
+    let mut nodes_per_scc: IndexVec<_, _> =
+        regioncx.constraint_sccs().all_sccs().map(|_| Vec::new()).collect();
+    for region in regioncx.var_infos.indices() {
+        let scc = regioncx.constraint_sccs().scc(region);
+        nodes_per_scc[scc].push(region);
+    }
+    for (scc, regions) in nodes_per_scc.iter_enumerated() {
+        // The node label: the regions contained in the SCC.
+        write!(out, "{scc}[\"SCC({scc}) = {{", scc = scc.as_usize())?;
+        for (idx, &region) in regions.iter().enumerate() {
+            render_region(region, regioncx, out)?;
+            if idx < regions.len() - 1 {
+                write!(out, ",")?;
+            }
+        }
+        writeln!(out, "}}\"]")?;
+    }
+
+    // Emit the edges between SCCs.
+    let edges = regioncx.constraint_sccs().all_sccs().flat_map(|source| {
+        regioncx.constraint_sccs().successors(source).iter().map(move |&target| (source, target))
+    });
+    for (source, target) in edges {
+        writeln!(out, "{} --> {}", source.as_usize(), target.as_usize())?;
+    }
+
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 2c99597922e8f..fdcd9caf4ac87 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -126,7 +126,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
         &mut self,
         name: &str,
         params: Vec<AbiParam>,
-        returns: Vec<AbiParam>,
+        mut returns: Vec<AbiParam>,
         args: &[Value],
     ) -> Cow<'_, [Value]> {
         // Pass i128 arguments by-ref on Windows.
@@ -150,15 +150,19 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
             (params, args.into())
         };
 
-        // Return i128 using a return area pointer on Windows and s390x.
-        let adjust_ret_param =
-            if self.tcx.sess.target.is_like_windows || self.tcx.sess.target.arch == "s390x" {
-                returns.len() == 1 && returns[0].value_type == types::I128
-            } else {
-                false
-            };
+        let ret_single_i128 = returns.len() == 1 && returns[0].value_type == types::I128;
+        if ret_single_i128 && self.tcx.sess.target.is_like_windows {
+            // Return i128 using the vector ABI on Windows
+            returns[0].value_type = types::I64X2;
+
+            let ret = self.lib_call_unadjusted(name, params, returns, &args)[0];
 
-        if adjust_ret_param {
+            // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128
+            let ret_ptr = self.create_stack_slot(16, 16);
+            ret_ptr.store(self, ret, MemFlags::trusted());
+            Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())])
+        } else if ret_single_i128 && self.tcx.sess.target.arch == "s390x" {
+            // Return i128 using a return area pointer on s390x.
             let mut params = params;
             let mut args = args.to_vec();
 
diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs
index 0b5cb1547fc69..4463631c524be 100644
--- a/compiler/rustc_codegen_cranelift/src/cast.rs
+++ b/compiler/rustc_codegen_cranelift/src/cast.rs
@@ -96,25 +96,9 @@ pub(crate) fn clif_int_or_float_cast(
                 },
             );
 
-            if fx.tcx.sess.target.is_like_windows {
-                let ret = fx.lib_call(
-                    &name,
-                    vec![AbiParam::new(from_ty)],
-                    vec![AbiParam::new(types::I64X2)],
-                    &[from],
-                )[0];
-                // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128
-                let ret_ptr = fx.create_stack_slot(16, 16);
-                ret_ptr.store(fx, ret, MemFlags::trusted());
-                ret_ptr.load(fx, types::I128, MemFlags::trusted())
-            } else {
-                fx.lib_call(
-                    &name,
-                    vec![AbiParam::new(from_ty)],
-                    vec![AbiParam::new(types::I128)],
-                    &[from],
-                )[0]
-            }
+            fx.lib_call(&name, vec![AbiParam::new(from_ty)], vec![AbiParam::new(types::I128)], &[
+                from,
+            ])[0]
         } else if to_ty == types::I8 || to_ty == types::I16 {
             // FIXME implement fcvt_to_*int_sat.i8/i16
             let val = if to_signed {
diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
index dcfd7ddabbc42..df5a79086fa3e 100644
--- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
+++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
@@ -33,28 +33,14 @@ pub(crate) fn maybe_codegen<'tcx>(
                 (BinOp::Rem, true) => "__modti3",
                 _ => unreachable!(),
             };
-            if fx.tcx.sess.target.is_like_windows {
-                let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
-                let ret = fx.lib_call(
-                    name,
-                    vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
-                    vec![AbiParam::new(types::I64X2)],
-                    &args,
-                )[0];
-                // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128
-                let ret_place = CPlace::new_stack_slot(fx, lhs.layout());
-                ret_place.to_ptr().store(fx, ret, MemFlags::trusted());
-                Some(ret_place.to_cvalue(fx))
-            } else {
-                let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
-                let ret_val = fx.lib_call(
-                    name,
-                    vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
-                    vec![AbiParam::new(types::I128)],
-                    &args,
-                )[0];
-                Some(CValue::by_val(ret_val, lhs.layout()))
-            }
+            let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
+            let ret_val = fx.lib_call(
+                name,
+                vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
+                vec![AbiParam::new(types::I128)],
+                &args,
+            )[0];
+            Some(CValue::by_val(ret_val, lhs.layout()))
         }
         BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne | BinOp::Cmp => None,
         BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None,
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 74d02ac22276c..9495030f124b5 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -797,7 +797,6 @@ fn test_unstable_options_tracking_hash() {
     tracked!(function_sections, Some(false));
     tracked!(human_readable_cgu_names, true);
     tracked!(incremental_ignore_spans, true);
-    tracked!(inline_in_all_cgus, Some(true));
     tracked!(inline_mir, Some(true));
     tracked!(inline_mir_hint_threshold, Some(123));
     tracked!(inline_mir_threshold, Some(123));
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 3eccf56d8c4dd..6fa3fa2432de5 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -91,13 +91,8 @@ impl<'tcx> MonoItem<'tcx> {
     }
 
     pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
-        let generate_cgu_internal_copies = tcx
-            .sess
-            .opts
-            .unstable_opts
-            .inline_in_all_cgus
-            .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
-            && !tcx.sess.link_dead_code();
+        let generate_cgu_internal_copies =
+            (tcx.sess.opts.optimize != OptLevel::No) && !tcx.sess.link_dead_code();
 
         match *self {
             MonoItem::Fn(ref instance) => {
@@ -121,8 +116,8 @@ impl<'tcx> MonoItem<'tcx> {
                 }
 
                 // At this point we don't have explicit linkage and we're an
-                // inlined function. If we're inlining into all CGUs then we'll
-                // be creating a local copy per CGU.
+                // inlined function. If this crate's build settings permit,
+                // we'll be creating a local copy per CGU.
                 if generate_cgu_internal_copies {
                     return InstantiationMode::LocalCopy;
                 }
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 50287b706ce83..2373ab67d42ed 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2830,9 +2830,10 @@ pub(crate) struct DynAfterMut {
 pub(crate) struct FnPointerCannotBeConst {
     #[primary_span]
     pub span: Span,
-    #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
     #[label]
     pub qualifier: Span,
+    #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
+    pub suggestion: Span,
 }
 
 #[derive(Diagnostic)]
@@ -2840,9 +2841,10 @@ pub(crate) struct FnPointerCannotBeConst {
 pub(crate) struct FnPointerCannotBeAsync {
     #[primary_span]
     pub span: Span,
-    #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
     #[label]
     pub qualifier: Span,
+    #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
+    pub suggestion: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 6497d19a173ca..dc5919b3630ce 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -609,16 +609,58 @@ impl<'a> Parser<'a> {
         let span_start = self.token.span;
         let ast::FnHeader { ext, safety, constness, coroutine_kind } =
             self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
+        let fn_start_lo = self.prev_token.span.lo();
         if self.may_recover() && self.token == TokenKind::Lt {
             self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
         }
         let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
         let whole_span = lo.to(self.prev_token.span);
-        if let ast::Const::Yes(span) = constness {
-            self.dcx().emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
+
+        // Order/parsing of "front matter" follows:
+        // `<constness> <coroutine_kind> <safety> <extern> fn()`
+        //  ^           ^                ^        ^        ^
+        //  |           |                |        |        fn_start_lo
+        //  |           |                |        ext_sp.lo
+        //  |           |                safety_sp.lo
+        //  |           coroutine_sp.lo
+        //  const_sp.lo
+        if let ast::Const::Yes(const_span) = constness {
+            let next_token_lo = if let Some(
+                ast::CoroutineKind::Async { span, .. }
+                | ast::CoroutineKind::Gen { span, .. }
+                | ast::CoroutineKind::AsyncGen { span, .. },
+            ) = coroutine_kind
+            {
+                span.lo()
+            } else if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety {
+                span.lo()
+            } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
+                span.lo()
+            } else {
+                fn_start_lo
+            };
+            let sugg_span = const_span.with_hi(next_token_lo);
+            self.dcx().emit_err(FnPointerCannotBeConst {
+                span: whole_span,
+                qualifier: const_span,
+                suggestion: sugg_span,
+            });
         }
-        if let Some(ast::CoroutineKind::Async { span, .. }) = coroutine_kind {
-            self.dcx().emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
+        if let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind {
+            let next_token_lo = if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety
+            {
+                span.lo()
+            } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
+                span.lo()
+            } else {
+                fn_start_lo
+            };
+            let sugg_span = async_span.with_hi(next_token_lo);
+            self.dcx().emit_err(FnPointerCannotBeAsync {
+                span: whole_span,
+                qualifier: async_span,
+                suggestion: sugg_span,
+            });
         }
         // FIXME(gen_blocks): emit a similar error for `gen fn()`
         let decl_span = span_start.to(self.prev_token.span);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 63aaa3abc8e56..4ce6382512978 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1870,8 +1870,6 @@ options! {
         "verify extended properties for incr. comp. (default: no):
         - hashes of green query instances
         - hash collisions of query keys"),
-    inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
-        "control whether `#[inline]` functions are in all CGUs"),
     inline_llvm: bool = (true, parse_bool, [TRACKED],
         "enable LLVM inlining (default: yes)"),
     inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs
index 0944bda26875d..816564d2fed8b 100644
--- a/compiler/rustc_target/src/callconv/x86_win64.rs
+++ b/compiler/rustc_target/src/callconv/x86_win64.rs
@@ -1,4 +1,4 @@
-use rustc_abi::{BackendRepr, Float, Primitive};
+use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind, Size};
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg};
 use crate::spec::HasTargetSpec;
@@ -6,7 +6,7 @@ use crate::spec::HasTargetSpec;
 // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
 
 pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
-    let fixup = |a: &mut ArgAbi<'_, Ty>| {
+    let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| {
         match a.layout.backend_repr {
             BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {}
             BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => {
@@ -23,11 +23,16 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<
                 // (probably what clang calls "illegal vectors").
             }
             BackendRepr::Scalar(scalar) => {
-                // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up
-                // with what LLVM expects.
-                if a.layout.size.bytes() > 8
+                if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) {
+                    // `i128` is returned in xmm0 by Clang and GCC
+                    // FIXME(#134288): This may change for the `-msvc` targets in the future.
+                    let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) };
+                    a.cast_to(reg);
+                } else if a.layout.size.bytes() > 8
                     && !matches!(scalar.primitive(), Primitive::Float(Float::F128))
                 {
+                    // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up
+                    // with what LLVM expects.
                     a.make_indirect();
                 } else {
                     a.extend_integer_width_to(32);
@@ -37,8 +42,9 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<
     };
 
     if !fn_abi.ret.is_ignore() {
-        fixup(&mut fn_abi.ret);
+        fixup(&mut fn_abi.ret, true);
     }
+
     for arg in fn_abi.args.iter_mut() {
         if arg.is_ignore() && arg.layout.is_zst() {
             // Windows ABIs do not talk about ZST since such types do not exist in MSVC.
@@ -49,7 +55,7 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<
             arg.make_indirect_from_ignore();
             continue;
         }
-        fixup(arg);
+        fixup(arg, false);
     }
     // FIXME: We should likely also do something about ZST return types, similar to above.
     // However, that's non-trivial due to `()`.
diff --git a/library/core/src/iter/sources/from_fn.rs b/library/core/src/iter/sources/from_fn.rs
index 5f3d404d7dca2..75cc0ffe3c77c 100644
--- a/library/core/src/iter/sources/from_fn.rs
+++ b/library/core/src/iter/sources/from_fn.rs
@@ -1,7 +1,7 @@
 use crate::fmt;
 
-/// Creates a new iterator where each iteration calls the provided closure
-/// `F: FnMut() -> Option<T>`.
+/// Creates an iterator with the provided closure
+/// `F: FnMut() -> Option<T>` as its `[next](Iterator::next)` method.
 ///
 /// The iterator will yield the `T`s returned from the closure.
 ///
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 4f37e18a8cd76..54a992c9cf4b5 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -324,6 +324,18 @@ impl f128 {
     ///
     /// The precision of this function is non-deterministic. This means it varies by platform,
     /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f128)]
+    ///
+    /// let x = 2.0_f128;
+    /// let abs_difference = (x.powi(2) - (x * x)).abs();
+    /// assert!(abs_difference <= f128::EPSILON);
+    ///
+    /// assert_eq!(f128::powi(f128::NAN, 0), 1.0);
+    /// ```
     #[inline]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
@@ -347,8 +359,10 @@ impl f128 {
     ///
     /// let x = 2.0_f128;
     /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
-    ///
     /// assert!(abs_difference <= f128::EPSILON);
+    ///
+    /// assert_eq!(f128::powf(1.0, f128::NAN), 1.0);
+    /// assert_eq!(f128::powf(f128::NAN, 0.0), 1.0);
     /// # }
     /// ```
     #[inline]
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index 42cd6e3fe2a5f..e354f2dd98217 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -324,6 +324,18 @@ impl f16 {
     ///
     /// The precision of this function is non-deterministic. This means it varies by platform,
     /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(f16)]
+    ///
+    /// let x = 2.0_f16;
+    /// let abs_difference = (x.powi(2) - (x * x)).abs();
+    /// assert!(abs_difference <= f16::EPSILON);
+    ///
+    /// assert_eq!(f16::powi(f16::NAN, 0), 1.0);
+    /// ```
     #[inline]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
@@ -347,8 +359,10 @@ impl f16 {
     ///
     /// let x = 2.0_f16;
     /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
-    ///
     /// assert!(abs_difference <= f16::EPSILON);
+    ///
+    /// assert_eq!(f16::powf(1.0, f16::NAN), 1.0);
+    /// assert_eq!(f16::powf(f16::NAN, 0.0), 1.0);
     /// # }
     /// ```
     #[inline]
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 438d77b1626be..f9b6723788ae3 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -306,8 +306,9 @@ impl f32 {
     /// ```
     /// let x = 2.0_f32;
     /// let abs_difference = (x.powi(2) - (x * x)).abs();
-    ///
     /// assert!(abs_difference <= f32::EPSILON);
+    ///
+    /// assert_eq!(f32::powi(f32::NAN, 0), 1.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
@@ -329,8 +330,10 @@ impl f32 {
     /// ```
     /// let x = 2.0_f32;
     /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
-    ///
     /// assert!(abs_difference <= f32::EPSILON);
+    ///
+    /// assert_eq!(f32::powf(1.0, f32::NAN), 1.0);
+    /// assert_eq!(f32::powf(f32::NAN, 0.0), 1.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 9bb4bfbab2a0f..0de55a15d48e8 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -306,8 +306,9 @@ impl f64 {
     /// ```
     /// let x = 2.0_f64;
     /// let abs_difference = (x.powi(2) - (x * x)).abs();
+    /// assert!(abs_difference <= f64::EPSILON);
     ///
-    /// assert!(abs_difference < 1e-10);
+    /// assert_eq!(f64::powi(f64::NAN, 0), 1.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
@@ -329,8 +330,10 @@ impl f64 {
     /// ```
     /// let x = 2.0_f64;
     /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
+    /// assert!(abs_difference <= f64::EPSILON);
     ///
-    /// assert!(abs_difference < 1e-10);
+    /// assert_eq!(f64::powf(1.0, f64::NAN), 1.0);
+    /// assert_eq!(f64::powf(f64::NAN, 0.0), 1.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
diff --git a/src/doc/book b/src/doc/book
index 82a4a49789bc9..fa312a343fbff 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 82a4a49789bc96db1a1b2a210b4c5ed7c9ef0c0d
+Subproject commit fa312a343fbff01bc6cef393e326817f70719813
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
index d56e0f3a0656b..4ed5a1a4a2a7e 160000
--- a/src/doc/edition-guide
+++ b/src/doc/edition-guide
@@ -1 +1 @@
-Subproject commit d56e0f3a0656b7702ca466d4b191e16c28262b82
+Subproject commit 4ed5a1a4a2a7ecc2e529a5baaef04f7bc7917eda
diff --git a/src/doc/nomicon b/src/doc/nomicon
index 625b200e5b33a..bc22988655446 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit 625b200e5b33a5af35589db0bc454203a3d46d20
+Subproject commit bc2298865544695c63454fc1f9f98a3dc22e9948
diff --git a/src/doc/reference b/src/doc/reference
index 293af99100377..93b921c7d3213 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 293af991003772bdccf2d6b980182d84dd055942
+Subproject commit 93b921c7d3213d38d920f7f905a3bec093d2217d
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index f92668a6a9786..2dfca7c4803e2 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -846,7 +846,6 @@ dependencies = [
  "dashmap",
  "hashbrown",
  "rustc-hash 2.0.0",
- "sptr",
  "triomphe",
 ]
 
@@ -1927,12 +1926,6 @@ dependencies = [
  "vfs",
 ]
 
-[[package]]
-name = "sptr"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a"
-
 [[package]]
 name = "stdx"
 version = "0.0.0"
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 1029844cd3ab4..c42ae171d8668 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
 resolver = "2"
 
 [workspace.package]
-rust-version = "1.83"
+rust-version = "1.84"
 edition = "2021"
 license = "MIT OR Apache-2.0"
 authors = ["rust-analyzer team"]
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 1327bb3ab59c0..16c7b5ca00a07 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -1381,6 +1381,9 @@ impl ExprCollector<'_> {
                 }
             }
             ast::Stmt::Item(ast::Item::MacroDef(macro_)) => {
+                if self.check_cfg(&macro_).is_none() {
+                    return;
+                }
                 let Some(name) = macro_.name() else {
                     statements.push(Statement::Item(Item::Other));
                     return;
@@ -1390,6 +1393,9 @@ impl ExprCollector<'_> {
                 self.collect_macro_def(statements, macro_id);
             }
             ast::Stmt::Item(ast::Item::MacroRules(macro_)) => {
+                if self.check_cfg(&macro_).is_none() {
+                    return;
+                }
                 let Some(name) = macro_.name() else {
                     statements.push(Statement::Item(Item::Other));
                     return;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
index f483efa85179b..e136dd18a55e5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
@@ -475,7 +475,7 @@ fn outer() {
 
             block scope::tests
             name: _
-            outer: v
+            outer: vg
 
             crate
             outer: v
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
index 5d67902c8ac12..c30ad0163b9db 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
@@ -445,6 +445,10 @@ fn find_in_dep(
         };
         cov_mark::hit!(partially_imported);
         if info.is_unstable {
+            if !ctx.cfg.allow_unstable {
+                // the item is unstable and we are not allowed to use unstable items
+                continue;
+            }
             choice.stability = Unstable;
         }
 
@@ -670,6 +674,7 @@ mod tests {
         prefer_prelude: bool,
         prefer_absolute: bool,
         prefer_no_std: bool,
+        allow_unstable: bool,
         expect: Expect,
     ) {
         let (db, pos) = TestDB::with_position(ra_fixture);
@@ -711,7 +716,7 @@ mod tests {
                 module,
                 prefix,
                 ignore_local_imports,
-                ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute },
+                ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute, allow_unstable },
             );
             format_to!(
                 res,
@@ -732,7 +737,7 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, false, false, false, expect);
+        check_found_path_(ra_fixture, path, false, false, false, false, expect);
     }
 
     fn check_found_path_prelude(
@@ -740,7 +745,7 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, true, false, false, expect);
+        check_found_path_(ra_fixture, path, true, false, false, false, expect);
     }
 
     fn check_found_path_absolute(
@@ -748,7 +753,7 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, false, true, false, expect);
+        check_found_path_(ra_fixture, path, false, true, false, false, expect);
     }
 
     fn check_found_path_prefer_no_std(
@@ -756,7 +761,15 @@ mod tests {
         path: &str,
         expect: Expect,
     ) {
-        check_found_path_(ra_fixture, path, false, false, true, expect);
+        check_found_path_(ra_fixture, path, false, false, true, false, expect);
+    }
+
+    fn check_found_path_prefer_no_std_allow_unstable(
+        #[rust_analyzer::rust_fixture] ra_fixture: &str,
+        path: &str,
+        expect: Expect,
+    ) {
+        check_found_path_(ra_fixture, path, false, false, true, true, expect);
     }
 
     #[test]
@@ -1951,7 +1964,7 @@ pub mod ops {
 
     #[test]
     fn respect_unstable_modules() {
-        check_found_path_prefer_no_std(
+        check_found_path_prefer_no_std_allow_unstable(
             r#"
 //- /main.rs crate:main deps:std,core
 extern crate std;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
index ac262950f13c6..34635997bdff3 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
@@ -10,7 +10,6 @@ use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
 use span::Edition;
 use stdx::{format_to, TupleExt};
-use syntax::ToSmolStr;
 use triomphe::Arc;
 
 use crate::{
@@ -88,9 +87,9 @@ impl ImportMap {
             .iter()
             // We've only collected items, whose name cannot be tuple field so unwrapping is fine.
             .flat_map(|(&item, (info, _))| {
-                info.iter().enumerate().map(move |(idx, info)| {
-                    (item, info.name.unescaped().display(db.upcast()).to_smolstr(), idx as u32)
-                })
+                info.iter()
+                    .enumerate()
+                    .map(move |(idx, info)| (item, info.name.as_str(), idx as u32))
             })
             .collect();
         importables.sort_by(|(_, l_info, _), (_, r_info, _)| {
@@ -168,7 +167,8 @@ impl ImportMap {
                     let attr_id = if let Some(import) = import {
                         match import {
                             ImportOrExternCrate::ExternCrate(id) => Some(id.into()),
-                            ImportOrExternCrate::Import(id) => Some(id.import.into()),
+                            ImportOrExternCrate::Import(id) => Some(id.use_.into()),
+                            ImportOrExternCrate::Glob(id) => Some(id.use_.into()),
                         }
                     } else {
                         match item {
@@ -441,7 +441,7 @@ pub fn search_dependencies(
 }
 
 fn search_maps(
-    db: &dyn DefDatabase,
+    _db: &dyn DefDatabase,
     import_maps: &[Arc<ImportMap>],
     mut stream: fst::map::Union<'_>,
     query: &Query,
@@ -464,11 +464,7 @@ fn search_maps(
                         .then(|| (item, &import_infos[info_idx as usize]))
                 })
                 .filter(|&(_, info)| {
-                    query.search_mode.check(
-                        &query.query,
-                        query.case_sensitive,
-                        &info.name.unescaped().display(db.upcast()).to_smolstr(),
-                    )
+                    query.search_mode.check(&query.query, query.case_sensitive, info.name.as_str())
                 });
             res.extend(iter.map(TupleExt::head));
         }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index 0fec7674109bc..65a39c565611b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -31,21 +31,62 @@ pub struct PerNsGlobImports {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrExternCrate {
+    Glob(GlobId),
     Import(ImportId),
     ExternCrate(ExternCrateId),
 }
 
+impl From<ImportOrGlob> for ImportOrExternCrate {
+    fn from(value: ImportOrGlob) -> Self {
+        match value {
+            ImportOrGlob::Glob(it) => ImportOrExternCrate::Glob(it),
+            ImportOrGlob::Import(it) => ImportOrExternCrate::Import(it),
+        }
+    }
+}
+
+impl ImportOrExternCrate {
+    pub fn import_or_glob(self) -> Option<ImportOrGlob> {
+        match self {
+            ImportOrExternCrate::Import(it) => Some(ImportOrGlob::Import(it)),
+            ImportOrExternCrate::Glob(it) => Some(ImportOrGlob::Glob(it)),
+            _ => None,
+        }
+    }
+
+    pub fn import(self) -> Option<ImportId> {
+        match self {
+            ImportOrExternCrate::Import(it) => Some(it),
+            _ => None,
+        }
+    }
+
+    pub fn glob(self) -> Option<GlobId> {
+        match self {
+            ImportOrExternCrate::Glob(id) => Some(id),
+            _ => None,
+        }
+    }
+
+    pub fn use_(self) -> Option<UseId> {
+        match self {
+            ImportOrExternCrate::Glob(id) => Some(id.use_),
+            ImportOrExternCrate::Import(id) => Some(id.use_),
+            _ => None,
+        }
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum ImportType {
+pub enum ImportOrGlob {
+    Glob(GlobId),
     Import(ImportId),
-    Glob(UseId),
-    ExternCrate(ExternCrateId),
 }
 
-impl ImportOrExternCrate {
+impl ImportOrGlob {
     pub fn into_import(self) -> Option<ImportId> {
         match self {
-            ImportOrExternCrate::Import(it) => Some(it),
+            ImportOrGlob::Import(it) => Some(it),
             _ => None,
         }
     }
@@ -54,12 +95,39 @@ impl ImportOrExternCrate {
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrDef {
     Import(ImportId),
+    Glob(GlobId),
     ExternCrate(ExternCrateId),
     Def(ModuleDefId),
 }
+
+impl From<ImportOrExternCrate> for ImportOrDef {
+    fn from(value: ImportOrExternCrate) -> Self {
+        match value {
+            ImportOrExternCrate::Import(it) => ImportOrDef::Import(it),
+            ImportOrExternCrate::Glob(it) => ImportOrDef::Glob(it),
+            ImportOrExternCrate::ExternCrate(it) => ImportOrDef::ExternCrate(it),
+        }
+    }
+}
+
+impl From<ImportOrGlob> for ImportOrDef {
+    fn from(value: ImportOrGlob) -> Self {
+        match value {
+            ImportOrGlob::Import(it) => ImportOrDef::Import(it),
+            ImportOrGlob::Glob(it) => ImportOrDef::Glob(it),
+        }
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub struct ImportId {
-    pub import: UseId,
+    pub use_: UseId,
+    pub idx: Idx<ast::UseTree>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub struct GlobId {
+    pub use_: UseId,
     pub idx: Idx<ast::UseTree>,
 }
 
@@ -96,8 +164,8 @@ pub struct ItemScope {
 
     // the resolutions of the imports of this scope
     use_imports_types: FxHashMap<ImportOrExternCrate, ImportOrDef>,
-    use_imports_values: FxHashMap<ImportId, ImportOrDef>,
-    use_imports_macros: FxHashMap<ImportId, ImportOrDef>,
+    use_imports_values: FxHashMap<ImportOrGlob, ImportOrDef>,
+    use_imports_macros: FxHashMap<ImportOrGlob, ImportOrDef>,
 
     use_decls: Vec<UseId>,
     extern_crate_decls: Vec<ExternCrateId>,
@@ -162,7 +230,7 @@ impl ItemScope {
             .map(move |name| (name, self.get(name)))
     }
 
-    pub fn values(&self) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportId>)> + '_ {
+    pub fn values(&self) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportOrGlob>)> + '_ {
         self.values.iter().map(|(n, &i)| (n, i))
     }
 
@@ -172,7 +240,7 @@ impl ItemScope {
         self.types.iter().map(|(n, &i)| (n, i))
     }
 
-    pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportId>)> + '_ {
+    pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportOrGlob>)> + '_ {
         self.macros.iter().map(|(n, &i)| (n, i))
     }
 
@@ -180,9 +248,10 @@ impl ItemScope {
         self.use_imports_types
             .keys()
             .copied()
-            .filter_map(ImportOrExternCrate::into_import)
+            .filter_map(ImportOrExternCrate::import_or_glob)
             .chain(self.use_imports_values.keys().copied())
             .chain(self.use_imports_macros.keys().copied())
+            .filter_map(ImportOrGlob::into_import)
             .sorted()
             .dedup()
     }
@@ -192,10 +261,10 @@ impl ItemScope {
 
         let mut def_map;
         let mut scope = self;
-        while let Some(&m) = scope.use_imports_macros.get(&import) {
+        while let Some(&m) = scope.use_imports_macros.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.import.lookup(db).container;
+                    let module_id = i.use_.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -211,7 +280,7 @@ impl ItemScope {
         while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.import.lookup(db).container;
+                    let module_id = i.use_.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -224,10 +293,10 @@ impl ItemScope {
             }
         }
         let mut scope = self;
-        while let Some(&m) = scope.use_imports_values.get(&import) {
+        while let Some(&m) = scope.use_imports_values.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.import.lookup(db).container;
+                    let module_id = i.use_.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -488,9 +557,13 @@ impl ItemScope {
         self.unnamed_trait_imports.get(&tr).map(|trait_| trait_.vis)
     }
 
-    pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
-        // FIXME: import
-        self.unnamed_trait_imports.insert(tr, Item { def: (), vis, import: None });
+    pub(crate) fn push_unnamed_trait(
+        &mut self,
+        tr: TraitId,
+        vis: Visibility,
+        import: Option<ImportId>,
+    ) {
+        self.unnamed_trait_imports.insert(tr, Item { def: (), vis, import });
     }
 
     pub(crate) fn push_res_with_import(
@@ -498,7 +571,7 @@ impl ItemScope {
         glob_imports: &mut PerNsGlobImports,
         lookup: (LocalModuleId, Name),
         def: PerNs,
-        import: Option<ImportType>,
+        import: Option<ImportOrExternCrate>,
     ) -> bool {
         let mut changed = false;
 
@@ -509,41 +582,22 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportType::Glob(_)) => {
+                        Some(ImportOrExternCrate::Glob(_)) => {
                             glob_imports.types.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.types.remove(&lookup),
                     }
-                    let import = match import {
-                        Some(ImportType::ExternCrate(extern_crate)) => {
-                            Some(ImportOrExternCrate::ExternCrate(extern_crate))
-                        }
-                        Some(ImportType::Import(import)) => {
-                            Some(ImportOrExternCrate::Import(import))
-                        }
-                        None | Some(ImportType::Glob(_)) => None,
-                    };
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
-                        self.use_imports_types.insert(
-                            import,
-                            match prev {
-                                Some(ImportOrExternCrate::Import(import)) => {
-                                    ImportOrDef::Import(import)
-                                }
-                                Some(ImportOrExternCrate::ExternCrate(import)) => {
-                                    ImportOrDef::ExternCrate(import)
-                                }
-                                None => ImportOrDef::Def(fld.def),
-                            },
-                        );
+                        self.use_imports_types
+                            .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
                     }
                     entry.insert(fld);
                     changed = true;
                 }
                 Entry::Occupied(mut entry) => {
                     match import {
-                        Some(ImportType::Glob(..)) => {
+                        Some(ImportOrExternCrate::Glob(..)) => {
                             // Multiple globs may import the same item and they may
                             // override visibility from previously resolved globs. This is
                             // currently handled by `DefCollector`, because we need to
@@ -552,28 +606,11 @@ impl ItemScope {
                         }
                         _ => {
                             if glob_imports.types.remove(&lookup) {
-                                let import = match import {
-                                    Some(ImportType::ExternCrate(extern_crate)) => {
-                                        Some(ImportOrExternCrate::ExternCrate(extern_crate))
-                                    }
-                                    Some(ImportType::Import(import)) => {
-                                        Some(ImportOrExternCrate::Import(import))
-                                    }
-                                    None | Some(ImportType::Glob(_)) => None,
-                                };
                                 let prev = std::mem::replace(&mut fld.import, import);
                                 if let Some(import) = import {
                                     self.use_imports_types.insert(
                                         import,
-                                        match prev {
-                                            Some(ImportOrExternCrate::Import(import)) => {
-                                                ImportOrDef::Import(import)
-                                            }
-                                            Some(ImportOrExternCrate::ExternCrate(import)) => {
-                                                ImportOrDef::ExternCrate(import)
-                                            }
-                                            None => ImportOrDef::Def(fld.def),
-                                        },
+                                        prev.map_or(ImportOrDef::Def(fld.def), Into::into),
                                     );
                                 }
                                 cov_mark::hit!(import_shadowed);
@@ -591,44 +628,31 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportType::Glob(_)) => {
+                        Some(ImportOrExternCrate::Glob(_)) => {
                             glob_imports.values.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.values.remove(&lookup),
                     }
-                    let import = match import {
-                        Some(ImportType::Import(import)) => Some(import),
-                        _ => None,
-                    };
+                    let import = import.and_then(ImportOrExternCrate::import_or_glob);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
-                        self.use_imports_values.insert(
-                            import,
-                            match prev {
-                                Some(import) => ImportOrDef::Import(import),
-                                None => ImportOrDef::Def(fld.def),
-                            },
-                        );
+                        self.use_imports_values
+                            .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
                     }
                     entry.insert(fld);
                     changed = true;
                 }
-                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
+                Entry::Occupied(mut entry)
+                    if !matches!(import, Some(ImportOrExternCrate::Glob(..))) =>
+                {
                     if glob_imports.values.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
-                        let import = match import {
-                            Some(ImportType::Import(import)) => Some(import),
-                            _ => None,
-                        };
+
+                        let import = import.and_then(ImportOrExternCrate::import_or_glob);
                         let prev = std::mem::replace(&mut fld.import, import);
                         if let Some(import) = import {
-                            self.use_imports_values.insert(
-                                import,
-                                match prev {
-                                    Some(import) => ImportOrDef::Import(import),
-                                    None => ImportOrDef::Def(fld.def),
-                                },
-                            );
+                            self.use_imports_values
+                                .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
                         }
                         entry.insert(fld);
                         changed = true;
@@ -643,43 +667,33 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportType::Glob(_)) => {
+                        Some(ImportOrExternCrate::Glob(_)) => {
                             glob_imports.macros.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.macros.remove(&lookup),
                     }
-                    let import = match import {
-                        Some(ImportType::Import(import)) => Some(import),
-                        _ => None,
-                    };
+                    let import = import.and_then(ImportOrExternCrate::import_or_glob);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
                         self.use_imports_macros.insert(
                             import,
-                            match prev {
-                                Some(import) => ImportOrDef::Import(import),
-                                None => ImportOrDef::Def(fld.def.into()),
-                            },
+                            prev.map_or_else(|| ImportOrDef::Def(fld.def.into()), Into::into),
                         );
                     }
                     entry.insert(fld);
                     changed = true;
                 }
-                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
+                Entry::Occupied(mut entry)
+                    if !matches!(import, Some(ImportOrExternCrate::Glob(..))) =>
+                {
                     if glob_imports.macros.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
-                        let import = match import {
-                            Some(ImportType::Import(import)) => Some(import),
-                            _ => None,
-                        };
+                        let import = import.and_then(ImportOrExternCrate::import_or_glob);
                         let prev = std::mem::replace(&mut fld.import, import);
                         if let Some(import) = import {
                             self.use_imports_macros.insert(
                                 import,
-                                match prev {
-                                    Some(import) => ImportOrDef::Import(import),
-                                    None => ImportOrDef::Def(fld.def.into()),
-                                },
+                                prev.map_or_else(|| ImportOrDef::Def(fld.def.into()), Into::into),
                             );
                         }
                         entry.insert(fld);
@@ -704,16 +718,27 @@ impl ItemScope {
             .map(|def| &mut def.vis)
             .chain(self.values.values_mut().map(|def| &mut def.vis))
             .chain(self.unnamed_trait_imports.values_mut().map(|def| &mut def.vis))
-            .for_each(|vis| {
-                *vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit)
+            .for_each(|vis| match vis {
+                &mut Visibility::Module(_, visibility_explicitness) => {
+                    *vis = Visibility::Module(this_module, visibility_explicitness)
+                }
+                Visibility::Public => {
+                    *vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit)
+                }
             });
 
         for mac in self.macros.values_mut() {
             if matches!(mac.def, MacroId::ProcMacroId(_) if mac.import.is_none()) {
                 continue;
             }
-
-            mac.vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit);
+            match mac.vis {
+                Visibility::Module(_, visibility_explicitness) => {
+                    mac.vis = Visibility::Module(this_module, visibility_explicitness)
+                }
+                Visibility::Public => {
+                    mac.vis = Visibility::Module(this_module, VisibilityExplicitness::Implicit)
+                }
+            }
         }
     }
 
@@ -732,20 +757,25 @@ impl ItemScope {
                 buf.push_str(" t");
                 match import {
                     Some(ImportOrExternCrate::Import(_)) => buf.push('i'),
+                    Some(ImportOrExternCrate::Glob(_)) => buf.push('g'),
                     Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'),
                     None => (),
                 }
             }
             if let Some(Item { import, .. }) = def.values {
                 buf.push_str(" v");
-                if import.is_some() {
-                    buf.push('i');
+                match import {
+                    Some(ImportOrGlob::Import(_)) => buf.push('i'),
+                    Some(ImportOrGlob::Glob(_)) => buf.push('g'),
+                    None => (),
                 }
             }
             if let Some(Item { import, .. }) = def.macros {
                 buf.push_str(" m");
-                if import.is_some() {
-                    buf.push('i');
+                match import {
+                    Some(ImportOrGlob::Import(_)) => buf.push('i'),
+                    Some(ImportOrGlob::Glob(_)) => buf.push('g'),
+                    None => (),
                 }
             }
             if def.is_none() {
@@ -828,7 +858,7 @@ impl PerNs {
         match def {
             ModuleDefId::ModuleId(_) => PerNs::types(def, v, import),
             ModuleDefId::FunctionId(_) => {
-                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::import_or_glob))
             }
             ModuleDefId::AdtId(adt) => match adt {
                 AdtId::UnionId(_) => PerNs::types(def, v, import),
@@ -843,14 +873,14 @@ impl PerNs {
             },
             ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import),
             ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => {
-                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::import_or_glob))
             }
             ModuleDefId::TraitId(_) => PerNs::types(def, v, import),
             ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import),
             ModuleDefId::MacroId(mac) => {
-                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::into_import))
+                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::import_or_glob))
             }
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index afdc49a2dc59a..e83ce6dc42cee 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -372,6 +372,7 @@ language_item_table! {
     DerefMut,                sym::deref_mut,           deref_mut_trait,            Target::Trait,          GenericRequirement::Exact(0);
     DerefTarget,             sym::deref_target,        deref_target,               Target::AssocTy,        GenericRequirement::None;
     Receiver,                sym::receiver,            receiver_trait,             Target::Trait,          GenericRequirement::None;
+    ReceiverTarget,           sym::receiver_target,     receiver_target,            Target::AssocTy,        GenericRequirement::None;
 
     Fn,                      sym::fn_,                 fn_trait,                   Target::Trait,          GenericRequirement::Exact(1);
     FnMut,                   sym::fn_mut,              fn_mut_trait,               Target::Trait,          GenericRequirement::Exact(1);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index 84c105a0a3467..c78818c642ceb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -114,6 +114,9 @@ pub struct ImportPathConfig {
     pub prefer_prelude: bool,
     /// If true, prefer abs path (starting with `::`) where it is available.
     pub prefer_absolute: bool,
+    /// If true, paths containing `#[unstable]` segments may be returned, but only if if there is no
+    /// stable path. This does not check, whether the item itself that is being imported is `#[unstable]`.
+    pub allow_unstable: bool,
 }
 
 #[derive(Debug)]
@@ -910,6 +913,7 @@ pub enum AssocItemId {
     ConstId(ConstId),
     TypeAliasId(TypeAliasId),
 }
+
 // FIXME: not every function, ... is actually an assoc item. maybe we should make
 // sure that you can only turn actual assoc items into AssocItemIds. This would
 // require not implementing From, and instead having some checked way of
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 1e4b42dff5fb7..06276335b7188 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -28,7 +28,7 @@ use triomphe::Arc;
 use crate::{
     attr::Attrs,
     db::DefDatabase,
-    item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
+    item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
     item_tree::{
         self, AttrOwner, FieldsShape, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
         ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind,
@@ -208,7 +208,7 @@ struct DefCollector<'a> {
     def_map: DefMap,
     // The dependencies of the current crate, including optional deps like `test`.
     deps: FxHashMap<Name, Dependency>,
-    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, UseId)>>,
+    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
     unresolved_imports: Vec<ImportDirective>,
     indeterminate_imports: Vec<(ImportDirective, PerNs)>,
     unresolved_macros: Vec<MacroDirective>,
@@ -524,11 +524,7 @@ impl DefCollector<'_> {
 
         match per_ns.types {
             Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => {
-                // FIXME: This should specifically look for a glob import somehow and record that here
-                self.def_map.prelude = Some((
-                    m,
-                    import.and_then(ImportOrExternCrate::into_import).map(|it| it.import),
-                ));
+                self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::use_)));
             }
             types => {
                 tracing::debug!(
@@ -845,13 +841,14 @@ impl DefCollector<'_> {
                     def.values = None;
                     def.macros = None;
                 }
-                let imp = ImportType::Import(ImportId { import: id, idx: use_tree });
+                let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree });
                 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
 
                 self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
             }
-            ImportSource { kind: ImportKind::Glob, id, is_prelude, .. } => {
+            ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree } => {
                 tracing::debug!("glob import: {:?}", import);
+                let glob = GlobId { use_: id, idx: use_tree };
                 match def.take_types() {
                     Some(ModuleDefId::ModuleId(m)) => {
                         if is_prelude {
@@ -875,7 +872,12 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
+                            self.update(
+                                module_id,
+                                &items,
+                                vis,
+                                Some(ImportOrExternCrate::Glob(glob)),
+                            );
                         } else {
                             // glob import from same crate => we do an initial
                             // import, and then need to propagate any further
@@ -907,11 +909,16 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
+                            self.update(
+                                module_id,
+                                &items,
+                                vis,
+                                Some(ImportOrExternCrate::Glob(glob)),
+                            );
                             // record the glob import in case we add further items
-                            let glob = self.glob_imports.entry(m.local_id).or_default();
-                            match glob.iter_mut().find(|(mid, _, _)| *mid == module_id) {
-                                None => glob.push((module_id, vis, id)),
+                            let glob_imports = self.glob_imports.entry(m.local_id).or_default();
+                            match glob_imports.iter_mut().find(|(mid, _, _)| *mid == module_id) {
+                                None => glob_imports.push((module_id, vis, glob)),
                                 Some((_, old_vis, _)) => {
                                     if let Some(new_vis) = old_vis.max(vis, &self.def_map) {
                                         *old_vis = new_vis;
@@ -944,7 +951,12 @@ impl DefCollector<'_> {
                             (Some(name), res)
                         })
                         .collect::<Vec<_>>();
-                        self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
+                        self.update(
+                            module_id,
+                            &resolutions,
+                            vis,
+                            Some(ImportOrExternCrate::Glob(glob)),
+                        );
                     }
                     Some(d) => {
                         tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -964,7 +976,7 @@ impl DefCollector<'_> {
         resolutions: &[(Option<Name>, PerNs)],
         // Visibility this import will have
         vis: Visibility,
-        import: Option<ImportType>,
+        import: Option<ImportOrExternCrate>,
     ) {
         self.db.unwind_if_cancelled();
         self.update_recursive(module_id, resolutions, vis, import, 0)
@@ -978,7 +990,7 @@ impl DefCollector<'_> {
         // All resolutions are imported with this visibility; the visibilities in
         // the `PerNs` values are ignored and overwritten
         vis: Visibility,
-        import: Option<ImportType>,
+        import: Option<ImportOrExternCrate>,
         depth: usize,
     ) {
         if GLOB_RECURSION_LIMIT.check(depth).is_err() {
@@ -994,8 +1006,10 @@ impl DefCollector<'_> {
                         self.push_res_and_update_glob_vis(module_id, name, *res, vis, import);
                 }
                 None => {
-                    let tr = match res.take_types() {
-                        Some(ModuleDefId::TraitId(tr)) => tr,
+                    let (tr, import) = match res.take_types_full() {
+                        Some(Item { def: ModuleDefId::TraitId(tr), vis: _, import }) => {
+                            (tr, import)
+                        }
                         Some(other) => {
                             tracing::debug!("non-trait `_` import of {:?}", other);
                             continue;
@@ -1021,7 +1035,11 @@ impl DefCollector<'_> {
 
                     if should_update {
                         changed = true;
-                        self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
+                        self.def_map.modules[module_id].scope.push_unnamed_trait(
+                            tr,
+                            vis,
+                            import.and_then(ImportOrExternCrate::import),
+                        );
                     }
                 }
             }
@@ -1043,13 +1061,13 @@ impl DefCollector<'_> {
             .cloned()
             .collect::<Vec<_>>();
 
-        for (glob_importing_module, glob_import_vis, use_) in glob_imports {
+        for (glob_importing_module, glob_import_vis, glob) in glob_imports {
             let vis = glob_import_vis.min(vis, &self.def_map).unwrap_or(glob_import_vis);
             self.update_recursive(
                 glob_importing_module,
                 resolutions,
                 vis,
-                Some(ImportType::Glob(use_)),
+                Some(ImportOrExternCrate::Glob(glob)),
                 depth + 1,
             );
         }
@@ -1061,7 +1079,7 @@ impl DefCollector<'_> {
         name: &Name,
         mut defs: PerNs,
         vis: Visibility,
-        def_import_type: Option<ImportType>,
+        def_import_type: Option<ImportOrExternCrate>,
     ) -> bool {
         // `extern crate crate_name` things can be re-exported as `pub use crate_name`.
         // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
@@ -1074,10 +1092,10 @@ impl DefCollector<'_> {
                 let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else {
                     return false;
                 };
-                let Some(ImportType::Import(id)) = def_import_type else {
+                let Some(ImportOrExternCrate::Import(id)) = def_import_type else {
                     return false;
                 };
-                let use_id = id.import.lookup(self.db).id;
+                let use_id = id.use_.lookup(self.db).id;
                 let item_tree = use_id.item_tree(self.db);
                 let use_kind = item_tree[use_id.value].use_tree.kind();
                 let UseTreeKind::Single { path, .. } = use_kind else {
@@ -1100,7 +1118,7 @@ impl DefCollector<'_> {
 
         let mut changed = false;
 
-        if let Some(ImportType::Glob(_)) = def_import_type {
+        if let Some(ImportOrExternCrate::Glob(_)) = def_import_type {
             let prev_defs = self.def_map[module_id].scope.get(name);
 
             // Multiple globs may import the same item and they may override visibility from
@@ -1727,7 +1745,7 @@ impl ModCollector<'_, '_> {
                                 ),
                             )],
                             vis,
-                            Some(ImportType::ExternCrate(id)),
+                            Some(ImportOrExternCrate::ExternCrate(id)),
                         );
                     } else {
                         if let Some(name) = name {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
index ab4ffbb2c1e4a..d7e4ca41cd5d5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
@@ -4,7 +4,6 @@ use base_db::AnchoredPath;
 use hir_expand::{name::Name, HirFileIdExt};
 use limit::Limit;
 use span::EditionedFileId;
-use syntax::ToSmolStr as _;
 
 use crate::{db::DefDatabase, HirFileId};
 
@@ -35,7 +34,7 @@ impl ModDir {
         let path = match attr_path {
             None => {
                 let mut path = self.dir_path.clone();
-                path.push(&name.unescaped().display_no_db().to_smolstr());
+                path.push(name.as_str());
                 path
             }
             Some(attr_path) => {
@@ -66,7 +65,7 @@ impl ModDir {
         name: &Name,
         attr_path: Option<&str>,
     ) -> Result<(EditionedFileId, bool, ModDir), Box<[String]>> {
-        let name = name.unescaped();
+        let name = name.as_str();
 
         let mut candidate_files = ArrayVec::<_, 2>::new();
         match attr_path {
@@ -74,16 +73,8 @@ impl ModDir {
                 candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
             }
             None => {
-                candidate_files.push(format!(
-                    "{}{}.rs",
-                    self.dir_path.0,
-                    name.display(db.upcast())
-                ));
-                candidate_files.push(format!(
-                    "{}{}/mod.rs",
-                    self.dir_path.0,
-                    name.display(db.upcast())
-                ));
+                candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
+                candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
             }
         };
 
@@ -97,7 +88,7 @@ impl ModDir {
                 let dir_path = if root_dir_owner {
                     DirPath::empty()
                 } else {
-                    DirPath::new(format!("{}/", name.display(db.upcast())))
+                    DirPath::new(format!("{}/", name))
                 };
                 if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
                     return Ok((
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
index 318aee04f7b7f..73fc6787bfe81 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
@@ -103,8 +103,8 @@ mod a {
             c: t
 
             crate::a::b::c
-            A: v
-            b: t
+            A: vg
+            b: tg
         "#]],
     );
 }
@@ -256,8 +256,8 @@ pub enum Foo { Bar, Baz }
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Baz: t v
+            Bar: tg vg
+            Baz: tg vg
         "#]],
     );
 }
@@ -421,10 +421,10 @@ pub struct NotExported;
 "#,
         expect![[r#"
             crate
-            Exported: t v
-            PublicItem: t v
-            allowed_reexport: t
-            exported: t
+            Exported: tg vg
+            PublicItem: tg vg
+            allowed_reexport: tg
+            exported: tg
             not_allowed_reexport1: _
             not_allowed_reexport2: _
         "#]],
@@ -692,7 +692,7 @@ mod b {
             b: t
 
             crate::a
-            T: t v
+            T: t vg
 
             crate::b
             T: v
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
index 8963a5767942e..ddb9d4a134d33 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
@@ -18,9 +18,9 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
-            Foo: t v
-            bar: t
+            Baz: tg vg
+            Foo: tg vg
+            bar: tg
             foo: t
 
             crate::foo
@@ -53,20 +53,20 @@ pub use super::*;
 "#,
         expect![[r#"
             crate
-            Baz: t v
-            Foo: t v
-            bar: t
+            Baz: tg vg
+            Foo: tg vg
+            bar: tg
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: tg vg
             Foo: t v
             bar: t
 
             crate::foo::bar
             Baz: t v
-            Foo: t v
-            bar: t
+            Foo: tg vg
+            bar: tg
         "#]],
     );
 }
@@ -91,20 +91,20 @@ pub use super::*;
 ",
         expect![[r#"
             crate
-            Baz: t v
-            bar: t
+            Baz: tg vg
+            bar: tg
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: tg vg
             PrivateStructFoo: t v
             bar: t
 
             crate::foo::bar
             Baz: t v
             PrivateStructBar: t v
-            PrivateStructFoo: t v
-            bar: t
+            PrivateStructFoo: tg vg
+            bar: tg
         "#]],
     );
 }
@@ -130,9 +130,9 @@ pub(crate) struct PubCrateStruct;
 ",
         expect![[r#"
             crate
-            Foo: t
-            PubCrateStruct: t v
-            bar: t
+            Foo: tg
+            PubCrateStruct: tg vg
+            bar: tg
             foo: t
 
             crate::foo
@@ -160,7 +160,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: tg vg
         "#]],
     );
 }
@@ -178,7 +178,7 @@ struct Foo;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: tg vg
         "#]],
     );
 }
@@ -193,8 +193,8 @@ use self::Foo::*;
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Baz: t v
+            Bar: tg vg
+            Baz: tg vg
             Foo: t
         "#]],
     );
@@ -210,8 +210,8 @@ use self::Foo::{*};
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Baz: t v
+            Bar: tg vg
+            Baz: tg vg
             Foo: t
         "#]],
     );
@@ -359,7 +359,7 @@ use event::Event;
             event: t
 
             crate::event
-            Event: t v
+            Event: t vg
             serenity: t
 
             crate::event::serenity
@@ -388,10 +388,10 @@ use reexport::*;
 "#,
         expect![[r#"
             crate
-            Trait: t
+            Trait: tg
             defs: t
-            function: v
-            makro: m
+            function: vg
+            makro: mg
             reexport: t
 
             crate::defs
@@ -400,10 +400,10 @@ use reexport::*;
             makro: m
 
             crate::reexport
-            Trait: t
-            function: v
+            Trait: tg
+            function: vg
             inner: t
-            makro: m
+            makro: mg
 
             crate::reexport::inner
             Trait: ti
@@ -442,12 +442,12 @@ mod glob_target {
             ShouldBePrivate: t v
 
             crate::outer
-            ShouldBePrivate: t v
+            ShouldBePrivate: tg vg
             inner_superglob: t
 
             crate::outer::inner_superglob
-            ShouldBePrivate: t v
-            inner_superglob: t
+            ShouldBePrivate: tg vg
+            inner_superglob: tg
         "#]],
     );
 }
@@ -473,20 +473,20 @@ use reexport_2::*;
 "#,
         expect![[r#"
             crate
-            Placeholder: t v
+            Placeholder: tg vg
             libs: t
-            reexport_1: t
+            reexport_1: tg
             reexport_2: t
 
             crate::libs
             Placeholder: t v
 
             crate::reexport_2
-            Placeholder: t v
+            Placeholder: tg vg
             reexport_1: t
 
             crate::reexport_2::reexport_1
-            Placeholder: t v
+            Placeholder: tg vg
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
index a05c4dcf9bd70..610886d55f40f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
@@ -97,9 +97,9 @@ macro_rules! structs {
             bar: t
 
             crate::bar
-            Bar: t
-            Foo: t
-            bar: t
+            Bar: tg
+            Foo: tg
+            bar: tg
         "#]],
     );
 }
@@ -130,9 +130,9 @@ macro_rules! structs {
             bar: t
 
             crate::bar
-            Bar: t
-            Foo: t
-            bar: t
+            Bar: tg
+            Foo: tg
+            bar: tg
         "#]],
     );
 }
@@ -169,9 +169,9 @@ macro_rules! inner {
             bar: t
 
             crate::bar
-            Bar: t
-            Foo: t
-            bar: t
+            Bar: tg
+            Foo: tg
+            bar: tg
         "#]],
     );
 }
@@ -794,7 +794,7 @@ pub trait Clone {}
 "#,
         expect![[r#"
             crate
-            Clone: t m
+            Clone: tg mg
         "#]],
     );
 }
@@ -1075,9 +1075,9 @@ macro_rules! mbe {
 "#,
         expect![[r#"
             crate
-            DummyTrait: m
-            attribute_macro: m
-            function_like_macro: m
+            DummyTrait: mg
+            attribute_macro: mg
+            function_like_macro: mg
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
index 899dd4afffef6..c2d3f67f17e77 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
@@ -6,7 +6,7 @@
 use bitflags::bitflags;
 
 use crate::{
-    item_scope::{ImportId, ImportOrExternCrate, ItemInNs},
+    item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob, ItemInNs},
     visibility::Visibility,
     MacroId, ModuleDefId,
 };
@@ -36,8 +36,8 @@ pub struct Item<Def, Import = ImportId> {
 }
 
 pub type TypesItem = Item<ModuleDefId, ImportOrExternCrate>;
-pub type ValuesItem = Item<ModuleDefId>;
-pub type MacrosItem = Item<MacroId>;
+pub type ValuesItem = Item<ModuleDefId, ImportOrGlob>;
+pub type MacrosItem = Item<MacroId, ImportOrGlob>;
 
 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
 pub struct PerNs {
@@ -59,7 +59,7 @@ impl PerNs {
         PerNs { types: None, values: None, macros: None }
     }
 
-    pub fn values(def: ModuleDefId, vis: Visibility, import: Option<ImportId>) -> PerNs {
+    pub fn values(def: ModuleDefId, vis: Visibility, import: Option<ImportOrGlob>) -> PerNs {
         PerNs { types: None, values: Some(Item { def, vis, import }), macros: None }
     }
 
@@ -78,13 +78,13 @@ impl PerNs {
             values: Some(Item {
                 def: values,
                 vis,
-                import: import.and_then(ImportOrExternCrate::into_import),
+                import: import.and_then(ImportOrExternCrate::import_or_glob),
             }),
             macros: None,
         }
     }
 
-    pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportId>) -> PerNs {
+    pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportOrGlob>) -> PerNs {
         PerNs { types: None, values: None, macros: Some(Item { def, vis, import }) }
     }
 
@@ -108,7 +108,7 @@ impl PerNs {
         self.values.map(|it| it.def)
     }
 
-    pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportId>)> {
+    pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportOrGlob>)> {
         self.values.map(|it| (it.def, it.import))
     }
 
@@ -116,7 +116,7 @@ impl PerNs {
         self.macros.map(|it| it.def)
     }
 
-    pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportId>)> {
+    pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportOrGlob>)> {
         self.macros.map(|it| (it.def, it.import))
     }
 
@@ -159,14 +159,12 @@ impl PerNs {
             .map(|it| (ItemInNs::Types(it.def), it.import))
             .into_iter()
             .chain(
-                self.values.map(|it| {
-                    (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::Import))
-                }),
+                self.values
+                    .map(|it| (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::from))),
             )
             .chain(
-                self.macros.map(|it| {
-                    (ItemInNs::Macros(it.def), it.import.map(ImportOrExternCrate::Import))
-                }),
+                self.macros
+                    .map(|it| (ItemInNs::Macros(it.def), it.import.map(ImportOrExternCrate::from))),
             )
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 0b9b6da8d5133..8c556d8a8c3f4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -19,7 +19,7 @@ use crate::{
     db::DefDatabase,
     generics::{GenericParams, TypeOrConstParamData},
     hir::{BindingId, ExprId, LabelId},
-    item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE},
+    item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE},
     lang_item::LangItemTarget,
     nameres::{DefMap, MacroSubNs, ResolvePathResultPrefixInfo},
     path::{ModPath, Path, PathKind},
@@ -107,7 +107,7 @@ pub enum TypeNs {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum ResolveValueResult {
-    ValueNs(ValueNs, Option<ImportId>),
+    ValueNs(ValueNs, Option<ImportOrGlob>),
     Partial(TypeNs, usize, Option<ImportOrExternCrate>),
 }
 
@@ -485,7 +485,7 @@ impl Resolver {
         db: &dyn DefDatabase,
         path: &ModPath,
         expected_macro_kind: Option<MacroSubNs>,
-    ) -> Option<(MacroId, Option<ImportId>)> {
+    ) -> Option<(MacroId, Option<ImportOrGlob>)> {
         let (item_map, module) = self.item_scope();
         item_map
             .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind)
@@ -1014,7 +1014,7 @@ impl ModuleItemMap {
     }
 }
 
-fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option<ImportId>)> {
+fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option<ImportOrGlob>)> {
     let (def, import) = per_ns.take_values_import()?;
     let res = match def {
         ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
index 89eae862bd96c..f0cf7ebf479f8 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
@@ -23,15 +23,6 @@ pub struct ModPath {
     segments: SmallVec<[Name; 1]>,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct UnescapedModPath<'a>(&'a ModPath);
-
-impl<'a> UnescapedModPath<'a> {
-    pub fn display(&'a self, db: &'a dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
-        UnescapedDisplay { db, path: self }
-    }
-}
-
 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum PathKind {
     Plain,
@@ -135,9 +126,11 @@ impl ModPath {
             _ => None,
         }
     }
-
-    pub fn unescaped(&self) -> UnescapedModPath<'_> {
-        UnescapedModPath(self)
+    pub fn display_verbatim<'a>(
+        &'a self,
+        db: &'a dyn crate::db::ExpandDatabase,
+    ) -> impl fmt::Display + 'a {
+        Display { db, path: self, edition: None }
     }
 
     pub fn display<'a>(
@@ -145,7 +138,7 @@ impl ModPath {
         db: &'a dyn crate::db::ExpandDatabase,
         edition: Edition,
     ) -> impl fmt::Display + 'a {
-        Display { db, path: self, edition }
+        Display { db, path: self, edition: Some(edition) }
     }
 }
 
@@ -158,23 +151,12 @@ impl Extend<Name> for ModPath {
 struct Display<'a> {
     db: &'a dyn ExpandDatabase,
     path: &'a ModPath,
-    edition: Edition,
+    edition: Option<Edition>,
 }
 
 impl fmt::Display for Display<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        display_fmt_path(self.db, self.path, f, Escape::IfNeeded(self.edition))
-    }
-}
-
-struct UnescapedDisplay<'a> {
-    db: &'a dyn ExpandDatabase,
-    path: &'a UnescapedModPath<'a>,
-}
-
-impl fmt::Display for UnescapedDisplay<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        display_fmt_path(self.db, self.path.0, f, Escape::No)
+        display_fmt_path(self.db, self.path, f, self.edition)
     }
 }
 
@@ -184,16 +166,11 @@ impl From<Name> for ModPath {
     }
 }
 
-enum Escape {
-    No,
-    IfNeeded(Edition),
-}
-
 fn display_fmt_path(
     db: &dyn ExpandDatabase,
     path: &ModPath,
     f: &mut fmt::Formatter<'_>,
-    escaped: Escape,
+    edition: Option<Edition>,
 ) -> fmt::Result {
     let mut first_segment = true;
     let mut add_segment = |s| -> fmt::Result {
@@ -221,10 +198,10 @@ fn display_fmt_path(
             f.write_str("::")?;
         }
         first_segment = false;
-        match escaped {
-            Escape::IfNeeded(edition) => segment.display(db, edition).fmt(f)?,
-            Escape::No => segment.unescaped().display(db).fmt(f)?,
-        }
+        match edition {
+            Some(edition) => segment.display(db, edition).fmt(f)?,
+            None => fmt::Display::fmt(segment.as_str(), f)?,
+        };
     }
     Ok(())
 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
index cc53d2e34aacb..848870c3a3844 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
@@ -4,8 +4,8 @@ use std::fmt;
 
 use intern::{sym, Symbol};
 use span::{Edition, SyntaxContextId};
-use syntax::ast;
 use syntax::utils::is_raw_identifier;
+use syntax::{ast, format_smolstr};
 
 /// `Name` is a wrapper around string, which is used in hir for both references
 /// and declarations. In theory, names should also carry hygiene info, but we are
@@ -51,33 +51,26 @@ impl PartialEq<Symbol> for Name {
     }
 }
 
+impl PartialEq<&Symbol> for Name {
+    fn eq(&self, &sym: &&Symbol) -> bool {
+        self.symbol == *sym
+    }
+}
+
 impl PartialEq<Name> for Symbol {
     fn eq(&self, name: &Name) -> bool {
         *self == name.symbol
     }
 }
 
-/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct UnescapedName<'a>(&'a Name);
-
-impl<'a> UnescapedName<'a> {
-    pub fn display(self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
-        _ = db;
-        UnescapedDisplay { name: self }
-    }
-    #[doc(hidden)]
-    pub fn display_no_db(self) -> impl fmt::Display + 'a {
-        UnescapedDisplay { name: self }
+impl PartialEq<Name> for &Symbol {
+    fn eq(&self, name: &Name) -> bool {
+        **self == name.symbol
     }
 }
 
 impl Name {
-    /// Note: this is private to make creating name from random string hard.
-    /// Hopefully, this should allow us to integrate hygiene cleaner in the
-    /// future, and to switch to interned representation of names.
     fn new_text(text: &str) -> Name {
-        debug_assert!(!text.starts_with("r#"));
         Name { symbol: Symbol::intern(text), ctx: () }
     }
 
@@ -87,12 +80,15 @@ impl Name {
         // Can't do that for all `SyntaxContextId`s because it breaks Salsa.
         ctx.remove_root_edition();
         _ = ctx;
-        Self::new_text(text)
+        match text.strip_prefix("r#") {
+            Some(text) => Self::new_text(text),
+            None => Self::new_text(text),
+        }
     }
 
     pub fn new_root(text: &str) -> Name {
         // The edition doesn't matter for hygiene.
-        Self::new(text.trim_start_matches("r#"), SyntaxContextId::root(Edition::Edition2015))
+        Self::new(text, SyntaxContextId::root(Edition::Edition2015))
     }
 
     pub fn new_tuple_field(idx: usize) -> Name {
@@ -119,12 +115,22 @@ impl Name {
     }
 
     pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
-        Self::new_text(lt.text().as_str().trim_start_matches("r#"))
+        let text = lt.text();
+        match text.strip_prefix("'r#") {
+            Some(text) => Self::new_text(&format_smolstr!("'{text}")),
+            None => Self::new_text(text.as_str()),
+        }
+    }
+
+    pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
+        debug_assert!(!symbol.as_str().starts_with("r#"));
+        _ = ctx;
+        Self { symbol, ctx: () }
     }
 
-    /// Resolve a name from the text of token.
-    fn resolve(raw_text: &str) -> Name {
-        Name::new_text(raw_text.trim_start_matches("r#"))
+    // FIXME: This needs to go once we have hygiene
+    pub fn new_symbol_root(sym: Symbol) -> Self {
+        Self::new_symbol(sym, SyntaxContextId::root(Edition::Edition2015))
     }
 
     /// A fake name for things missing in the source code.
@@ -161,22 +167,19 @@ impl Name {
         self.symbol.as_str().parse().ok()
     }
 
+    /// Whether this name needs to be escaped in the given edition via `r#`.
+    pub fn needs_escape(&self, edition: Edition) -> bool {
+        is_raw_identifier(self.symbol.as_str(), edition)
+    }
+
     /// Returns the text this name represents if it isn't a tuple field.
     ///
     /// Do not use this for user-facing text, use `display` instead to handle editions properly.
+    // FIXME: This should take a database argument to hide the interning
     pub fn as_str(&self) -> &str {
         self.symbol.as_str()
     }
 
-    // FIXME: Remove this
-    pub fn unescaped(&self) -> UnescapedName<'_> {
-        UnescapedName(self)
-    }
-
-    pub fn needs_escape(&self, edition: Edition) -> bool {
-        is_raw_identifier(self.symbol.as_str(), edition)
-    }
-
     pub fn display<'a>(
         &'a self,
         db: &dyn crate::db::ExpandDatabase,
@@ -186,7 +189,7 @@ impl Name {
         self.display_no_db(edition)
     }
 
-    // FIXME: Remove this
+    // FIXME: Remove this in favor of `display`, see fixme on `as_str`
     #[doc(hidden)]
     pub fn display_no_db(&self, edition: Edition) -> impl fmt::Display + '_ {
         Display { name: self, needs_escaping: is_raw_identifier(self.symbol.as_str(), edition) }
@@ -195,24 +198,6 @@ impl Name {
     pub fn symbol(&self) -> &Symbol {
         &self.symbol
     }
-
-    pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
-        debug_assert!(!symbol.as_str().starts_with("r#"));
-        _ = ctx;
-        Self { symbol, ctx: () }
-    }
-
-    // FIXME: This needs to go once we have hygiene
-    pub fn new_symbol_root(sym: Symbol) -> Self {
-        debug_assert!(!sym.as_str().starts_with("r#"));
-        Self { symbol: sym, ctx: () }
-    }
-
-    // FIXME: Remove this
-    #[inline]
-    pub fn eq_ident(&self, ident: &str) -> bool {
-        self.as_str() == ident.trim_start_matches("r#")
-    }
 }
 
 struct Display<'a> {
@@ -229,17 +214,6 @@ impl fmt::Display for Display<'_> {
     }
 }
 
-struct UnescapedDisplay<'a> {
-    name: UnescapedName<'a>,
-}
-
-impl fmt::Display for UnescapedDisplay<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let symbol = self.name.0.symbol.as_str();
-        fmt::Display::fmt(symbol, f)
-    }
-}
-
 pub trait AsName {
     fn as_name(&self) -> Name;
 }
@@ -248,14 +222,14 @@ impl AsName for ast::NameRef {
     fn as_name(&self) -> Name {
         match self.as_tuple_field() {
             Some(idx) => Name::new_tuple_field(idx),
-            None => Name::resolve(&self.text()),
+            None => Name::new_root(&self.text()),
         }
     }
 }
 
 impl AsName for ast::Name {
     fn as_name(&self) -> Name {
-        Name::resolve(&self.text())
+        Name::new_root(&self.text())
     }
 }
 
@@ -270,7 +244,7 @@ impl AsName for ast::NameOrNameRef {
 
 impl<Span> AsName for tt::Ident<Span> {
     fn as_name(&self) -> Name {
-        Name::resolve(self.sym.as_str())
+        Name::new_root(self.sym.as_str())
     }
 }
 
@@ -288,6 +262,6 @@ impl AsName for ast::FieldKind {
 
 impl AsName for base_db::Dependency {
     fn as_name(&self) -> Name {
-        Name::new_text(&self.name)
+        Name::new_root(&self.name)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
index 2b5342314a65a..62feca5f8cbbf 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -17,7 +17,7 @@ use crate::{
     TraitEnvironment, Ty, TyBuilder, TyKind,
 };
 
-static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
+static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(20);
 
 #[derive(Debug)]
 pub(crate) enum AutoderefKind {
@@ -39,7 +39,7 @@ pub fn autoderef(
 ) -> impl Iterator<Item = Ty> {
     let mut table = InferenceTable::new(db, env);
     let ty = table.instantiate_canonical(ty);
-    let mut autoderef = Autoderef::new_no_tracking(&mut table, ty, false);
+    let mut autoderef = Autoderef::new_no_tracking(&mut table, ty, false, false);
     let mut v = Vec::new();
     while let Some((ty, _steps)) = autoderef.next() {
         // `ty` may contain unresolved inference variables. Since there's no chance they would be
@@ -49,7 +49,7 @@ pub fn autoderef(
         // If the deref chain contains a cycle (e.g. `A` derefs to `B` and `B` derefs to `A`), we
         // would revisit some already visited types. Stop here to avoid duplication.
         //
-        // XXX: The recursion limit for `Autoderef` is currently 10, so `Vec::contains()` shouldn't
+        // XXX: The recursion limit for `Autoderef` is currently 20, so `Vec::contains()` shouldn't
         // be too expensive. Replace this duplicate check with `FxHashSet` if it proves to be more
         // performant.
         if v.contains(&resolved) {
@@ -89,12 +89,18 @@ pub(crate) struct Autoderef<'table, 'db, T = Vec<(AutoderefKind, Ty)>> {
     at_start: bool,
     steps: T,
     explicit: bool,
+    use_receiver_trait: bool,
 }
 
 impl<'table, 'db> Autoderef<'table, 'db> {
-    pub(crate) fn new(table: &'table mut InferenceTable<'db>, ty: Ty, explicit: bool) -> Self {
+    pub(crate) fn new(
+        table: &'table mut InferenceTable<'db>,
+        ty: Ty,
+        explicit: bool,
+        use_receiver_trait: bool,
+    ) -> Self {
         let ty = table.resolve_ty_shallow(&ty);
-        Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit }
+        Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait }
     }
 
     pub(crate) fn steps(&self) -> &[(AutoderefKind, Ty)] {
@@ -107,9 +113,10 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> {
         table: &'table mut InferenceTable<'db>,
         ty: Ty,
         explicit: bool,
+        use_receiver_trait: bool,
     ) -> Self {
         let ty = table.resolve_ty_shallow(&ty);
-        Autoderef { table, ty, at_start: true, steps: 0, explicit }
+        Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait }
     }
 }
 
@@ -137,7 +144,8 @@ impl<T: TrackAutoderefSteps> Iterator for Autoderef<'_, '_, T> {
             return None;
         }
 
-        let (kind, new_ty) = autoderef_step(self.table, self.ty.clone(), self.explicit)?;
+        let (kind, new_ty) =
+            autoderef_step(self.table, self.ty.clone(), self.explicit, self.use_receiver_trait)?;
 
         self.steps.push(kind, &self.ty);
         self.ty = new_ty;
@@ -150,11 +158,12 @@ pub(crate) fn autoderef_step(
     table: &mut InferenceTable<'_>,
     ty: Ty,
     explicit: bool,
+    use_receiver_trait: bool,
 ) -> Option<(AutoderefKind, Ty)> {
     if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
         Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
     } else {
-        Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
+        Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?))
     }
 }
 
@@ -176,6 +185,7 @@ pub(crate) fn builtin_deref<'ty>(
 pub(crate) fn deref_by_trait(
     table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>,
     ty: Ty,
+    use_receiver_trait: bool,
 ) -> Option<Ty> {
     let _p = tracing::info_span!("deref_by_trait").entered();
     if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
@@ -183,14 +193,25 @@ pub(crate) fn deref_by_trait(
         return None;
     }
 
-    let deref_trait =
-        db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
+    let trait_id = || {
+        if use_receiver_trait {
+            if let Some(receiver) =
+                db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait())
+            {
+                return Some(receiver);
+            }
+        }
+        // Old rustc versions might not have `Receiver` trait.
+        // Fallback to `Deref` if they don't
+        db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())
+    };
+    let trait_id = trait_id()?;
     let target = db
-        .trait_data(deref_trait)
+        .trait_data(trait_id)
         .associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?;
 
     let projection = {
-        let b = TyBuilder::subst_for_def(db, deref_trait, None);
+        let b = TyBuilder::subst_for_def(db, trait_id, None);
         if b.remaining() != 1 {
             // the Target type + Deref trait should only have one generic parameter,
             // namely Deref's Self type
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
index 4991d173b9c42..774991560e9ca 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -231,8 +231,7 @@ impl<'a> DeclValidator<'a> {
             .filter_map(|(pat_id, pat)| match pat {
                 Pat::Bind { id, .. } => {
                     let bind_name = &body.bindings[*id].name;
-                    let mut suggested_text =
-                        to_lower_snake_case(&bind_name.unescaped().display_no_db().to_smolstr())?;
+                    let mut suggested_text = to_lower_snake_case(bind_name.as_str())?;
                     if is_raw_identifier(&suggested_text, edition) {
                         suggested_text.insert_str(0, "r#");
                     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 3545bf7677671..ae8fbe2ce6d76 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -34,6 +34,7 @@ use rustc_apfloat::{
     ieee::{Half as f16, Quad as f128},
     Float,
 };
+use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
 use span::Edition;
 use stdx::never;
@@ -87,6 +88,35 @@ pub struct HirFormatter<'a> {
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
     display_target: DisplayTarget,
+    bounds_formatting_ctx: BoundsFormattingCtx,
+}
+
+#[derive(Default)]
+enum BoundsFormattingCtx {
+    Entered {
+        /// We can have recursive bounds like the following case:
+        /// ```rust
+        /// where
+        ///     T: Foo,
+        ///     T::FooAssoc: Baz<<T::FooAssoc as Bar>::BarAssoc> + Bar
+        /// ```
+        /// So, record the projection types met while formatting bounds and
+        //. prevent recursing into their bounds to avoid infinite loops.
+        projection_tys_met: FxHashSet<ProjectionTy>,
+    },
+    #[default]
+    Exited,
+}
+
+impl BoundsFormattingCtx {
+    fn contains(&mut self, proj: &ProjectionTy) -> bool {
+        match self {
+            BoundsFormattingCtx::Entered { projection_tys_met } => {
+                projection_tys_met.contains(proj)
+            }
+            BoundsFormattingCtx::Exited => false,
+        }
+    }
 }
 
 impl HirFormatter<'_> {
@@ -97,6 +127,30 @@ impl HirFormatter<'_> {
     fn end_location_link(&mut self) {
         self.fmt.end_location_link();
     }
+
+    fn format_bounds_with<T, F: FnOnce(&mut Self) -> T>(
+        &mut self,
+        target: ProjectionTy,
+        format_bounds: F,
+    ) -> T {
+        match self.bounds_formatting_ctx {
+            BoundsFormattingCtx::Entered { ref mut projection_tys_met } => {
+                projection_tys_met.insert(target);
+                format_bounds(self)
+            }
+            BoundsFormattingCtx::Exited => {
+                let mut projection_tys_met = FxHashSet::default();
+                projection_tys_met.insert(target);
+                self.bounds_formatting_ctx = BoundsFormattingCtx::Entered { projection_tys_met };
+                let res = format_bounds(self);
+                // Since we want to prevent only the infinite recursions in bounds formatting
+                // and do not want to skip formatting of other separate bounds, clear context
+                // when exiting the formatting of outermost bounds
+                self.bounds_formatting_ctx = BoundsFormattingCtx::Exited;
+                res
+            }
+        }
+    }
 }
 
 pub trait HirDisplay {
@@ -220,6 +274,7 @@ pub trait HirDisplay {
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
             show_container_bounds: false,
+            bounds_formatting_ctx: Default::default(),
         }) {
             Ok(()) => {}
             Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
@@ -427,6 +482,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
             display_target: self.display_target,
             closure_style: self.closure_style,
             show_container_bounds: self.show_container_bounds,
+            bounds_formatting_ctx: Default::default(),
         })
     }
 
@@ -479,42 +535,46 @@ impl HirDisplay for ProjectionTy {
         // `<Param as Trait>::Assoc`
         if !f.display_target.is_source_code() {
             if let TyKind::Placeholder(idx) = self_ty.kind(Interner) {
-                let db = f.db;
-                let id = from_placeholder_idx(db, *idx);
-                let generics = generics(db.upcast(), id.parent);
-
-                let substs = generics.placeholder_subst(db);
-                let bounds = db
-                    .generic_predicates(id.parent)
-                    .iter()
-                    .map(|pred| pred.clone().substitute(Interner, &substs))
-                    .filter(|wc| match wc.skip_binders() {
-                        WhereClause::Implemented(tr) => {
-                            match tr.self_type_parameter(Interner).kind(Interner) {
-                                TyKind::Alias(AliasTy::Projection(proj)) => proj == self,
-                                _ => false,
+                if !f.bounds_formatting_ctx.contains(self) {
+                    let db = f.db;
+                    let id = from_placeholder_idx(db, *idx);
+                    let generics = generics(db.upcast(), id.parent);
+
+                    let substs = generics.placeholder_subst(db);
+                    let bounds = db
+                        .generic_predicates(id.parent)
+                        .iter()
+                        .map(|pred| pred.clone().substitute(Interner, &substs))
+                        .filter(|wc| match wc.skip_binders() {
+                            WhereClause::Implemented(tr) => {
+                                matches!(
+                                    tr.self_type_parameter(Interner).kind(Interner),
+                                    TyKind::Alias(_)
+                                )
                             }
-                        }
-                        WhereClause::TypeOutlives(t) => match t.ty.kind(Interner) {
-                            TyKind::Alias(AliasTy::Projection(proj)) => proj == self,
-                            _ => false,
-                        },
-                        // We shouldn't be here if these exist
-                        WhereClause::AliasEq(_) => false,
-                        WhereClause::LifetimeOutlives(_) => false,
-                    })
-                    .collect::<Vec<_>>();
-                if !bounds.is_empty() {
-                    return write_bounds_like_dyn_trait_with_prefix(
-                        f,
-                        "impl",
-                        Either::Left(
-                            &TyKind::Alias(AliasTy::Projection(self.clone())).intern(Interner),
-                        ),
-                        &bounds,
-                        SizedByDefault::NotSized,
-                    );
-                };
+                            WhereClause::TypeOutlives(t) => {
+                                matches!(t.ty.kind(Interner), TyKind::Alias(_))
+                            }
+                            // We shouldn't be here if these exist
+                            WhereClause::AliasEq(_) => false,
+                            WhereClause::LifetimeOutlives(_) => false,
+                        })
+                        .collect::<Vec<_>>();
+                    if !bounds.is_empty() {
+                        return f.format_bounds_with(self.clone(), |f| {
+                            write_bounds_like_dyn_trait_with_prefix(
+                                f,
+                                "impl",
+                                Either::Left(
+                                    &TyKind::Alias(AliasTy::Projection(self.clone()))
+                                        .intern(Interner),
+                                ),
+                                &bounds,
+                                SizedByDefault::NotSized,
+                            )
+                        });
+                    }
+                }
             }
         }
 
@@ -1159,6 +1219,7 @@ impl HirDisplay for Ty {
                                 prefer_no_std: false,
                                 prefer_prelude: true,
                                 prefer_absolute: false,
+                                allow_unstable: true,
                             },
                         ) {
                             write!(f, "{}", path.display(f.db.upcast(), f.edition()))?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index 2523aba538334..9283c46d0f611 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -277,7 +277,7 @@ impl CapturedItem {
     /// Converts the place to a name that can be inserted into source code.
     pub fn place_to_name(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
         let body = db.body(owner);
-        let mut result = body[self.place.local].name.unescaped().display(db.upcast()).to_string();
+        let mut result = body[self.place.local].name.as_str().to_owned();
         for proj in &self.place.projections {
             match proj {
                 ProjectionElem::Deref => {}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index 2fe90a8a92432..d40816ba8ced2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
@@ -420,7 +420,7 @@ impl InferenceTable<'_> {
 
         let snapshot = self.snapshot();
 
-        let mut autoderef = Autoderef::new(self, from_ty.clone(), false);
+        let mut autoderef = Autoderef::new(self, from_ty.clone(), false, false);
         let mut first_error = None;
         let mut found = None;
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 6b6c0348dcb4f..b951443897cb0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -487,7 +487,7 @@ impl InferenceContext<'_> {
             }
             Expr::Call { callee, args, .. } => {
                 let callee_ty = self.infer_expr(*callee, &Expectation::none(), ExprIsRead::Yes);
-                let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false);
+                let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false, true);
                 let (res, derefed_callee) = loop {
                     let Some((callee_deref_ty, _)) = derefs.next() else {
                         break (None, callee_ty.clone());
@@ -854,7 +854,7 @@ impl InferenceContext<'_> {
                         if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
                             self.resolve_ty_shallow(derefed)
                         } else {
-                            deref_by_trait(&mut self.table, inner_ty)
+                            deref_by_trait(&mut self.table, inner_ty, false)
                                 .unwrap_or_else(|| self.err_ty())
                         }
                     }
@@ -1718,7 +1718,7 @@ impl InferenceContext<'_> {
         receiver_ty: &Ty,
         name: &Name,
     ) -> Option<(Ty, Either<FieldId, TupleFieldId>, Vec<Adjustment>, bool)> {
-        let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false);
+        let mut autoderef = Autoderef::new(&mut self.table, receiver_ty.clone(), false, false);
         let mut private_field = None;
         let res = autoderef.by_ref().find_map(|(derefed_ty, _)| {
             let (field_id, parameters) = match derefed_ty.kind(Interner) {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index 182032f04812d..1cea67ee96419 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -528,7 +528,7 @@ impl ReceiverAdjustments {
         let mut ty = table.resolve_ty_shallow(&ty);
         let mut adjust = Vec::new();
         for _ in 0..self.autoderefs {
-            match autoderef::autoderef_step(table, ty.clone(), true) {
+            match autoderef::autoderef_step(table, ty.clone(), true, false) {
                 None => {
                     never!("autoderef not possible for {:?}", ty);
                     ty = TyKind::Error.intern(Interner);
@@ -1106,7 +1106,8 @@ fn iterate_method_candidates_by_receiver(
     // be found in any of the derefs of receiver_ty, so we have to go through
     // that, including raw derefs.
     table.run_in_snapshot(|table| {
-        let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true);
+        let mut autoderef =
+            autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
         while let Some((self_ty, _)) = autoderef.next() {
             iterate_inherent_methods(
                 &self_ty,
@@ -1123,7 +1124,8 @@ fn iterate_method_candidates_by_receiver(
         ControlFlow::Continue(())
     })?;
     table.run_in_snapshot(|table| {
-        let mut autoderef = autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true);
+        let mut autoderef =
+            autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
         while let Some((self_ty, _)) = autoderef.next() {
             if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
                 // don't try to resolve methods on unknown types
@@ -1709,7 +1711,7 @@ fn autoderef_method_receiver(
     ty: Ty,
 ) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
     let mut deref_chain: Vec<_> = Vec::new();
-    let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty, false);
+    let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty, false, true);
     while let Some((ty, derefs)) = autoderef.next() {
         deref_chain.push((
             autoderef.table.canonicalize(ty),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index 74acf23b75ab6..8866de22dfb99 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -1343,7 +1343,7 @@ fn foo<T: Trait>(a: &T) {
 fn autoderef_visibility_field() {
     check(
         r#"
-//- minicore: deref
+//- minicore: receiver
 mod a {
     pub struct Foo(pub char);
     pub struct Bar(i32);
@@ -1375,7 +1375,7 @@ fn autoderef_visibility_method() {
     cov_mark::check!(autoderef_candidate_not_visible);
     check(
         r#"
-//- minicore: deref
+//- minicore: receiver
 mod a {
     pub struct Foo(pub char);
     impl Foo {
@@ -1741,7 +1741,7 @@ fn main() {
 fn deref_fun_1() {
     check_types(
         r#"
-//- minicore: deref
+//- minicore: receiver
 
 struct A<T, U>(T, U);
 struct B<T>(T);
@@ -1782,7 +1782,7 @@ fn test() {
 fn deref_fun_2() {
     check_types(
         r#"
-//- minicore: deref
+//- minicore: receiver
 
 struct A<T, U>(T, U);
 struct B<T>(T);
@@ -1903,7 +1903,7 @@ pub fn test(generic_args: impl Into<Foo>) {
 fn bad_inferred_reference_2() {
     check_no_mismatches(
         r#"
-//- minicore: deref
+//- minicore: receiver
 trait ExactSizeIterator {
     fn len(&self) -> usize;
 }
@@ -2054,7 +2054,7 @@ fn foo() {
 fn box_deref_is_builtin() {
     check(
         r#"
-//- minicore: deref
+//- minicore: receiver
 use core::ops::Deref;
 
 #[lang = "owned_box"]
@@ -2087,7 +2087,7 @@ fn test() {
 fn manually_drop_deref_is_not_builtin() {
     check(
         r#"
-//- minicore: manually_drop, deref
+//- minicore: manually_drop, receiver
 struct Foo;
 impl Foo {
     fn foo(&self) {}
@@ -2105,7 +2105,7 @@ fn test() {
 fn mismatched_args_due_to_supertraits_with_deref() {
     check_no_mismatches(
         r#"
-//- minicore: deref
+//- minicore: receiver
 use core::ops::Deref;
 
 trait Trait1 {
@@ -2139,3 +2139,34 @@ fn problem_method<T: Trait3>() {
 "#,
     );
 }
+
+#[test]
+fn receiver_without_deref_impl() {
+    check(
+        r#"
+//- minicore: receiver
+use core::ops::Receiver;
+
+struct Foo;
+
+impl Foo {
+    fn foo1(self: &Bar) -> i32 { 42 }
+    fn foo2(self: Bar) -> bool { true }
+}
+
+struct Bar;
+
+impl Receiver for Bar {
+    type Target = Foo;
+}
+
+fn main() {
+    let bar = Bar;
+    let _v1 = bar.foo1();
+      //^^^ type: i32
+    let _v2 = bar.foo2();
+      //^^^ type: bool
+}
+"#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index db3121d3cd35f..0cbc75726bf39 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -45,7 +45,7 @@ use hir_def::{
     body::BodyDiagnostic,
     data::{adt::VariantData, TraitFlags},
     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
-    hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
+    hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat},
     item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
     lang_item::LangItemTarget,
     layout::{self, ReprOptions, TargetDataLayout},
@@ -2470,20 +2470,31 @@ impl Param {
     }
 
     pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
-        let parent = match self.func {
-            Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
-            Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
-            _ => return None,
-        };
-        let body = db.body(parent);
-        if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
-            Some(Local { parent, binding_id: self_param })
-        } else if let Pat::Bind { id, .. } =
-            &body[body.params[self.idx - body.self_param.is_some() as usize]]
-        {
-            Some(Local { parent, binding_id: *id })
-        } else {
-            None
+        match self.func {
+            Callee::Def(CallableDefId::FunctionId(it)) => {
+                let parent = DefWithBodyId::FunctionId(it);
+                let body = db.body(parent);
+                if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
+                    Some(Local { parent, binding_id: self_param })
+                } else if let Pat::Bind { id, .. } =
+                    &body[body.params[self.idx - body.self_param.is_some() as usize]]
+                {
+                    Some(Local { parent, binding_id: *id })
+                } else {
+                    None
+                }
+            }
+            Callee::Closure(closure, _) => {
+                let c = db.lookup_intern_closure(closure.into());
+                let body = db.body(c.0);
+                if let Expr::Closure { args, .. } = &body[c.1] {
+                    if let Pat::Bind { id, .. } = &body[args[self.idx]] {
+                        return Some(Local { parent: c.0, binding_id: *id });
+                    }
+                }
+                None
+            }
+            _ => None,
         }
     }
 
@@ -2756,6 +2767,15 @@ impl Trait {
         traits.iter().map(|tr| Trait::from(*tr)).collect()
     }
 
+    pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
+        db.trait_data(self.id).items.iter().find(|(n, _)| name == *n).and_then(
+            |&(_, it)| match it {
+                AssocItemId::FunctionId(id) => Some(Function { id }),
+                _ => None,
+            },
+        )
+    }
+
     pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
         db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
     }
@@ -4673,6 +4693,10 @@ impl Type {
         matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
     }
 
+    pub fn is_str(&self) -> bool {
+        matches!(self.ty.kind(Interner), TyKind::Str)
+    }
+
     pub fn is_never(&self) -> bool {
         matches!(self.ty.kind(Interner), TyKind::Never)
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 523bc6f10aab6..09470bed9cfb4 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -1439,8 +1439,20 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call)
     }
 
-    pub fn resolve_known_blanket_dual_impls(&self, call: &ast::MethodCallExpr) -> Option<Function> {
-        self.analyze(call.syntax())?.resolve_known_blanket_dual_impls(self.db, call)
+    /// Env is used to derive the trait environment
+    // FIXME: better api for the trait environment
+    pub fn resolve_trait_impl_method(
+        &self,
+        env: Type,
+        trait_: Trait,
+        func: Function,
+        subst: impl IntoIterator<Item = Type>,
+    ) -> Option<Function> {
+        let mut substs = hir_ty::TyBuilder::subst_for_def(self.db, TraitId::from(trait_), None);
+        for s in subst {
+            substs = substs.push(s.ty);
+        }
+        Some(self.db.lookup_impl_method(env.env, func.into(), substs.build()).0.into())
     }
 
     fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> {
@@ -1471,6 +1483,8 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(try_expr.syntax())?.resolve_try_expr(self.db, try_expr)
     }
 
+    // This does not resolve the method call to the correct trait impl!
+    // We should probably fix that.
     pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
         self.analyze(call.syntax())?.resolve_method_call_as_callable(self.db, call)
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 6b78d7a3631fa..b699ccde4128e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -322,68 +322,6 @@ impl SourceAnalyzer {
         }
     }
 
-    // If the method is into(), try_into(), parse(), resolve it to from, try_from, from_str.
-    pub(crate) fn resolve_known_blanket_dual_impls(
-        &self,
-        db: &dyn HirDatabase,
-        call: &ast::MethodCallExpr,
-    ) -> Option<Function> {
-        // e.g. if the method call is let b = a.into(),
-        // - receiver_type is A (type of a)
-        // - return_type is B (type of b)
-        // We will find the definition of B::from(a: A).
-        let callable = self.resolve_method_call_as_callable(db, call)?;
-        let (_, receiver_type) = callable.receiver_param(db)?;
-        let return_type = callable.return_type();
-        let (search_method, substs) = match call.name_ref()?.text().as_str() {
-            "into" => {
-                let trait_ =
-                    self.resolver.resolve_known_trait(db.upcast(), &path![core::convert::From])?;
-                (
-                    self.trait_fn(db, trait_, "from")?,
-                    hir_ty::TyBuilder::subst_for_def(db, trait_, None)
-                        .push(return_type.ty)
-                        .push(receiver_type.ty)
-                        .build(),
-                )
-            }
-            "try_into" => {
-                let trait_ = self
-                    .resolver
-                    .resolve_known_trait(db.upcast(), &path![core::convert::TryFrom])?;
-                (
-                    self.trait_fn(db, trait_, "try_from")?,
-                    hir_ty::TyBuilder::subst_for_def(db, trait_, None)
-                        // If the method is try_into() or parse(), return_type is Result<T, Error>.
-                        // Get T from type arguments of Result<T, Error>.
-                        .push(return_type.type_arguments().next()?.ty)
-                        .push(receiver_type.ty)
-                        .build(),
-                )
-            }
-            "parse" => {
-                let trait_ =
-                    self.resolver.resolve_known_trait(db.upcast(), &path![core::str::FromStr])?;
-                (
-                    self.trait_fn(db, trait_, "from_str")?,
-                    hir_ty::TyBuilder::subst_for_def(db, trait_, None)
-                        .push(return_type.type_arguments().next()?.ty)
-                        .build(),
-                )
-            }
-            _ => return None,
-        };
-
-        let found_method = self.resolve_impl_method_or_trait_def(db, search_method, substs);
-        // If found_method == search_method, the method in trait itself is resolved.
-        // It means the blanket dual impl is not found.
-        if found_method == search_method {
-            None
-        } else {
-            Some(found_method.into())
-        }
-    }
-
     pub(crate) fn resolve_expr_as_callable(
         &self,
         db: &dyn HirDatabase,
@@ -1309,18 +1247,6 @@ impl SourceAnalyzer {
         Some((trait_id, fn_id))
     }
 
-    fn trait_fn(
-        &self,
-        db: &dyn HirDatabase,
-        trait_id: TraitId,
-        method_name: &str,
-    ) -> Option<FunctionId> {
-        db.trait_data(trait_id).items.iter().find_map(|(item_name, item)| match item {
-            AssocItemId::FunctionId(t) if item_name.as_str() == method_name => Some(*t),
-            _ => None,
-        })
-    }
-
     fn ty_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<&Ty> {
         self.infer.as_ref()?.type_of_expr_or_pat(self.expr_id(db, expr)?)
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index a6b8ed70c363a..2ebd88edae2d7 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -3,7 +3,7 @@
 use either::Either;
 use hir_def::{
     db::DefDatabase,
-    item_scope::{ImportId, ImportOrExternCrate},
+    item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob},
     per_ns::Item,
     src::{HasChildSource, HasSource},
     visibility::{Visibility, VisibilityExplicitness},
@@ -55,9 +55,10 @@ impl DeclarationLocation {
 }
 
 /// Represents an outstanding module that the symbol collector must collect symbols from.
+#[derive(Debug)]
 struct SymbolCollectorWork {
     module_id: ModuleId,
-    parent: Option<DefWithBodyId>,
+    parent: Option<Name>,
 }
 
 pub struct SymbolCollector<'a> {
@@ -81,7 +82,15 @@ impl<'a> SymbolCollector<'a> {
         }
     }
 
+    pub fn new_module(db: &dyn HirDatabase, module: Module) -> Box<[FileSymbol]> {
+        let mut symbol_collector = SymbolCollector::new(db);
+        symbol_collector.collect(module);
+        symbol_collector.finish()
+    }
+
     pub fn collect(&mut self, module: Module) {
+        let _p = tracing::info_span!("SymbolCollector::collect", ?module).entered();
+        tracing::info!(?module, "SymbolCollector::collect",);
         self.edition = module.krate().edition(self.db);
 
         // The initial work is the root module we're collecting, additional work will
@@ -97,16 +106,12 @@ impl<'a> SymbolCollector<'a> {
         self.symbols.into_iter().collect()
     }
 
-    pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Box<[FileSymbol]> {
-        let mut symbol_collector = SymbolCollector::new(db);
-        symbol_collector.collect(module);
-        symbol_collector.finish()
-    }
-
     fn do_work(&mut self, work: SymbolCollectorWork) {
+        let _p = tracing::info_span!("SymbolCollector::do_work", ?work).entered();
+        tracing::info!(?work, "SymbolCollector::do_work");
         self.db.unwind_if_cancelled();
 
-        let parent_name = work.parent.and_then(|id| self.def_with_body_id_name(id));
+        let parent_name = work.parent.map(|name| name.as_str().to_smolstr());
         self.with_container_name(parent_name, |s| s.collect_from_module(work.module_id));
     }
 
@@ -116,18 +121,18 @@ impl<'a> SymbolCollector<'a> {
                 ModuleDefId::ModuleId(id) => this.push_module(id, name),
                 ModuleDefId::FunctionId(id) => {
                     this.push_decl(id, name, false);
-                    this.collect_from_body(id);
+                    this.collect_from_body(id, Some(name.clone()));
                 }
                 ModuleDefId::AdtId(AdtId::StructId(id)) => this.push_decl(id, name, false),
                 ModuleDefId::AdtId(AdtId::EnumId(id)) => this.push_decl(id, name, false),
                 ModuleDefId::AdtId(AdtId::UnionId(id)) => this.push_decl(id, name, false),
                 ModuleDefId::ConstId(id) => {
                     this.push_decl(id, name, false);
-                    this.collect_from_body(id);
+                    this.collect_from_body(id, Some(name.clone()));
                 }
                 ModuleDefId::StaticId(id) => {
                     this.push_decl(id, name, false);
-                    this.collect_from_body(id);
+                    this.collect_from_body(id, Some(name.clone()));
                 }
                 ModuleDefId::TraitId(id) => {
                     this.push_decl(id, name, false);
@@ -153,24 +158,32 @@ impl<'a> SymbolCollector<'a> {
         // Nested trees are very common, so a cache here will hit a lot.
         let import_child_source_cache = &mut FxHashMap::default();
 
-        let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId| {
+        let is_explicit_import = |vis| match vis {
+            Visibility::Public => true,
+            Visibility::Module(_, VisibilityExplicitness::Explicit) => true,
+            Visibility::Module(_, VisibilityExplicitness::Implicit) => false,
+        };
+
+        let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId, vis| {
             let source = import_child_source_cache
-                .entry(i.import)
-                .or_insert_with(|| i.import.child_source(this.db.upcast()));
+                .entry(i.use_)
+                .or_insert_with(|| i.use_.child_source(this.db.upcast()));
             let Some(use_tree_src) = source.value.get(i.idx) else { return };
-            let Some(name_ptr) = use_tree_src
-                .rename()
-                .and_then(|rename| rename.name())
-                .map(Either::Left)
-                .or_else(|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right))
-                .map(|it| AstPtr::new(&it))
-            else {
+            let rename = use_tree_src.rename().and_then(|rename| rename.name());
+            let name_syntax = match rename {
+                Some(name) => Some(Either::Left(name)),
+                None if is_explicit_import(vis) => {
+                    (|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right))()
+                }
+                None => None,
+            };
+            let Some(name_syntax) = name_syntax else {
                 return;
             };
             let dec_loc = DeclarationLocation {
                 hir_file_id: source.file_id,
                 ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
-                name_ptr,
+                name_ptr: AstPtr::new(&name_syntax),
             };
             this.symbols.insert(FileSymbol {
                 name: name.symbol().clone(),
@@ -183,23 +196,23 @@ impl<'a> SymbolCollector<'a> {
         };
 
         let push_extern_crate =
-            |this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId| {
+            |this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId, vis| {
                 let loc = i.lookup(this.db.upcast());
                 let source = loc.source(this.db.upcast());
-                let Some(name_ptr) = source
-                    .value
-                    .rename()
-                    .and_then(|rename| rename.name())
-                    .map(Either::Left)
-                    .or_else(|| source.value.name_ref().map(Either::Right))
-                    .map(|it| AstPtr::new(&it))
-                else {
+                let rename = source.value.rename().and_then(|rename| rename.name());
+
+                let name_syntax = match rename {
+                    Some(name) => Some(Either::Left(name)),
+                    None if is_explicit_import(vis) => None,
+                    None => source.value.name_ref().map(Either::Right),
+                };
+                let Some(name_syntax) = name_syntax else {
                     return;
                 };
                 let dec_loc = DeclarationLocation {
                     hir_file_id: source.file_id,
                     ptr: SyntaxNodePtr::new(source.value.syntax()),
-                    name_ptr,
+                    name_ptr: AstPtr::new(&name_syntax),
                 };
                 this.symbols.insert(FileSymbol {
                     name: name.symbol().clone(),
@@ -211,18 +224,6 @@ impl<'a> SymbolCollector<'a> {
                 });
             };
 
-        let is_explicit_import = |vis| {
-            match vis {
-                Visibility::Module(_, VisibilityExplicitness::Explicit) => true,
-                Visibility::Module(_, VisibilityExplicitness::Implicit) => {
-                    // consider imports in the crate root explicit, as these are visibly
-                    // crate-wide anyways
-                    module_id.is_crate_root()
-                }
-                Visibility::Public => true,
-            }
-        };
-
         let def_map = module_id.def_map(self.db.upcast());
         let scope = &def_map[module_id.local_id].scope;
 
@@ -232,14 +233,14 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.types() {
             if let Some(i) = import {
-                if is_explicit_import(vis) {
-                    match i {
-                        ImportOrExternCrate::Import(i) => push_import(self, i, name, def),
-                        ImportOrExternCrate::ExternCrate(i) => {
-                            push_extern_crate(self, i, name, def)
-                        }
+                match i {
+                    ImportOrExternCrate::Import(i) => push_import(self, i, name, def, vis),
+                    ImportOrExternCrate::Glob(_) => (),
+                    ImportOrExternCrate::ExternCrate(i) => {
+                        push_extern_crate(self, i, name, def, vis)
                     }
                 }
+
                 continue;
             }
             // self is a declaration
@@ -248,8 +249,9 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.macros() {
             if let Some(i) = import {
-                if is_explicit_import(vis) {
-                    push_import(self, i, name, def.into());
+                match i {
+                    ImportOrGlob::Import(i) => push_import(self, i, name, def.into(), vis),
+                    ImportOrGlob::Glob(_) => (),
                 }
                 continue;
             }
@@ -259,8 +261,9 @@ impl<'a> SymbolCollector<'a> {
 
         for (name, Item { def, vis, import }) in scope.values() {
             if let Some(i) = import {
-                if is_explicit_import(vis) {
-                    push_import(self, i, name, def);
+                match i {
+                    ImportOrGlob::Import(i) => push_import(self, i, name, def, vis),
+                    ImportOrGlob::Glob(_) => (),
                 }
                 continue;
             }
@@ -269,7 +272,7 @@ impl<'a> SymbolCollector<'a> {
         }
 
         for const_id in scope.unnamed_consts() {
-            self.collect_from_body(const_id);
+            self.collect_from_body(const_id, None);
         }
 
         for (name, id) in scope.legacy_macros() {
@@ -285,7 +288,7 @@ impl<'a> SymbolCollector<'a> {
         }
     }
 
-    fn collect_from_body(&mut self, body_id: impl Into<DefWithBodyId>) {
+    fn collect_from_body(&mut self, body_id: impl Into<DefWithBodyId>, name: Option<Name>) {
         let body_id = body_id.into();
         let body = self.db.body(body_id);
 
@@ -294,7 +297,7 @@ impl<'a> SymbolCollector<'a> {
             for (id, _) in def_map.modules() {
                 self.work.push(SymbolCollectorWork {
                     module_id: def_map.module_id(id),
-                    parent: Some(body_id),
+                    parent: name.clone(),
                 });
             }
         }
@@ -333,24 +336,6 @@ impl<'a> SymbolCollector<'a> {
         }
     }
 
-    fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> {
-        match body_id {
-            DefWithBodyId::FunctionId(id) => {
-                Some(self.db.function_data(id).name.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::StaticId(id) => {
-                Some(self.db.static_data(id).name.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::ConstId(id) => {
-                Some(self.db.const_data(id).name.as_ref()?.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::VariantId(id) => {
-                Some(self.db.enum_variant_data(id).name.display_no_db(self.edition).to_smolstr())
-            }
-            DefWithBodyId::InTypeConstId(_) => Some("in type const".into()),
-        }
-    }
-
     fn push_assoc_item(&mut self, assoc_item_id: AssocItemId, name: &Name) {
         match assoc_item_id {
             AssocItemId::FunctionId(id) => self.push_decl(id, name, true),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
index 82d8db4258924..fb533077d9626 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
@@ -28,6 +28,7 @@ impl AssistConfig {
             prefer_no_std: self.prefer_no_std,
             prefer_prelude: self.prefer_prelude,
             prefer_absolute: self.prefer_absolute,
+            allow_unstable: true,
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
index a5c5b08d5b0c7..eb784cd1226fd 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
@@ -159,7 +159,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
     };
     // Verify this is `bool::then` that is being called.
     let func = ctx.sema.resolve_method_call(&mcall)?;
-    if !func.name(ctx.sema.db).eq_ident("then") {
+    if func.name(ctx.sema.db) != sym::then {
         return None;
     }
     let assoc = func.as_assoc_item(ctx.sema.db)?;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
index bb04a43cf9615..d34cf895cd90a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
@@ -343,11 +343,9 @@ fn compute_closure_type_params(
     let mut mentioned_names = mentioned_generic_params
         .iter()
         .filter_map(|param| match param {
-            hir::GenericParam::TypeParam(param) => {
-                Some(param.name(ctx.db()).unescaped().display(ctx.db()).to_smolstr())
-            }
+            hir::GenericParam::TypeParam(param) => Some(param.name(ctx.db()).as_str().to_smolstr()),
             hir::GenericParam::ConstParam(param) => {
-                Some(param.name(ctx.db()).unescaped().display(ctx.db()).to_smolstr())
+                Some(param.name(ctx.db()).as_str().to_smolstr())
             }
             hir::GenericParam::LifetimeParam(_) => None,
         })
@@ -390,7 +388,7 @@ fn compute_closure_type_params(
             let has_name = syntax
                 .descendants()
                 .filter_map(ast::NameOrNameRef::cast)
-                .any(|name| mentioned_names.contains(&*name.text()));
+                .any(|name| mentioned_names.contains(name.text().trim_start_matches("r#")));
             let mut has_new_params = false;
             if has_name {
                 syntax
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
index 615b5d3f98b55..d4f2ea3bd941b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -170,7 +170,7 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Va
             ),
             _ => false,
         })
-        .any(|(name, _)| name.eq_ident(variant_name.text().as_str()))
+        .any(|(name, _)| name.as_str() == variant_name.text().trim_start_matches("r#"))
 }
 
 fn extract_generic_params(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
index 97321f4ec1ef0..7b6f76d00452e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
@@ -1672,8 +1672,8 @@ macro_rules! vec {
     () => {Vec}
 }
 fn main() {
-    let $0vec = vec![];
-    let _ = vec;
+    let $0items = vec![];
+    let _ = items;
 }
 "#,
             "Extract into variable",
@@ -1696,8 +1696,8 @@ macro_rules! vec {
     () => {Vec}
 }
 fn main() {
-    const $0VEC: Vec = vec![];
-    let _ = VEC;
+    const $0ITEMS: Vec = vec![];
+    let _ = ITEMS;
 }
 "#,
             "Extract into constant",
@@ -1720,8 +1720,8 @@ macro_rules! vec {
     () => {Vec}
 }
 fn main() {
-    static $0VEC: Vec = vec![];
-    let _ = VEC;
+    static $0ITEMS: Vec = vec![];
+    let _ = ITEMS;
 }
 "#,
             "Extract into static",
@@ -2019,8 +2019,8 @@ impl<T> Vec<T> {
 }
 
 fn foo(s: &mut S) {
-    let $0vec = &mut s.vec;
-    vec.push(0);
+    let $0items = &mut s.vec;
+    items.push(0);
 }"#,
             "Extract into variable",
         );
@@ -2106,8 +2106,8 @@ impl<T> Vec<T> {
 }
 
 fn foo(f: &mut Y) {
-    let $0vec = &mut f.field.field.vec;
-    vec.push(0);
+    let $0items = &mut f.field.field.vec;
+    items.push(0);
 }"#,
             "Extract into variable",
         );
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs
index 7a92d8911bf85..47e4a68293f0c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -48,7 +48,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
     let (_, def) = module
         .scope(ctx.db(), None)
         .into_iter()
-        .find(|(name, _)| name.eq_ident(name_ref.text().as_str()))?;
+        .find(|(name, _)| name.as_str() == name_ref.text().trim_start_matches("r#"))?;
     let ScopeDef::ModuleDef(def) = def else {
         return None;
     };
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs
index 8a7a06b380f51..10915f8aafb8d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs
@@ -2,7 +2,7 @@ use ide_db::{
     assists::{AssistId, AssistKind},
     base_db::AnchoredPathBuf,
 };
-use syntax::{ast, AstNode};
+use syntax::{ast, AstNode, ToSmolStr};
 
 use crate::{
     assist_context::{AssistContext, Assists},
@@ -39,7 +39,7 @@ pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
     }
 
     let target = source_file.syntax().text_range();
-    let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
+    let module_name = module.name(ctx.db())?.as_str().to_smolstr();
     let path = format!("../{module_name}.rs");
     let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
     acc.add(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs
index 9692b70592912..bbf18e21948eb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_module_to_file.rs
@@ -61,7 +61,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) ->
                                 .string_value_unescape()
                                 .is_none() =>
                     {
-                        format_to!(buf, "{}/", name.unescaped().display(db))
+                        format_to!(buf, "{}/", name.as_str())
                     }
                     _ => (),
                 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs
index 2925e2334b44d..7b38c795dc80f 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs
@@ -2,7 +2,7 @@ use ide_db::{
     assists::{AssistId, AssistKind},
     base_db::AnchoredPathBuf,
 };
-use syntax::{ast, AstNode};
+use syntax::{ast, AstNode, ToSmolStr};
 
 use crate::{
     assist_context::{AssistContext, Assists},
@@ -39,7 +39,7 @@ pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
     }
 
     let target = source_file.syntax().text_range();
-    let module_name = module.name(ctx.db())?.unescaped().display(ctx.db()).to_string();
+    let module_name = module.name(ctx.db())?.as_str().to_smolstr();
     let path = format!("./{module_name}/mod.rs");
     let dst = AnchoredPathBuf { anchor: ctx.file_id().into(), path };
     acc.add(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
index 849b8a42c6949..2a8465f634cfb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
@@ -208,7 +208,7 @@ fn find_trait_method(
     if let Some(hir::AssocItem::Function(method)) =
         trait_.items(db).into_iter().find(|item: &hir::AssocItem| {
             item.name(db)
-                .map(|name| name.eq_ident(trait_method_name.text().as_str()))
+                .map(|name| name.as_str() == trait_method_name.text().trim_start_matches("r#"))
                 .unwrap_or(false)
         })
     {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
index 972303c2a0416..a79a82be45079 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
@@ -110,7 +110,7 @@ fn compute_fields_ranks(
         .fields(ctx.db())
         .into_iter()
         .enumerate()
-        .map(|(idx, field)| (field.name(ctx.db()).unescaped().display(ctx.db()).to_string(), idx))
+        .map(|(idx, field)| (field.name(ctx.db()).as_str().to_owned(), idx))
         .collect();
 
     Some(res)
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs
index eb1d538f8743a..c3404173eafe6 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_impl_items.rs
@@ -122,7 +122,7 @@ fn compute_item_ranks(
             .iter()
             .flat_map(|i| i.name(ctx.db()))
             .enumerate()
-            .map(|(idx, name)| (name.unescaped().display(ctx.db()).to_string(), idx))
+            .map(|(idx, name)| (name.as_str().to_owned(), idx))
             .collect(),
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
index 40669c65c5766..a22e7b272ea05 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
@@ -188,9 +188,6 @@ impl Completions {
         resolution: hir::ScopeDef,
         doc_aliases: Vec<syntax::SmolStr>,
     ) {
-        if !ctx.check_stability(resolution.attrs(ctx.db).as_deref()) {
-            return;
-        }
         let is_private_editable = match ctx.def_is_visible(&resolution) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -216,9 +213,6 @@ impl Completions {
         local_name: hir::Name,
         resolution: hir::ScopeDef,
     ) {
-        if !ctx.check_stability(resolution.attrs(ctx.db).as_deref()) {
-            return;
-        }
         let is_private_editable = match ctx.def_is_visible(&resolution) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -241,7 +235,7 @@ impl Completions {
         path_ctx: &PathCompletionCtx,
         e: hir::Enum,
     ) {
-        if !ctx.check_stability(Some(&e.attrs(ctx.db))) {
+        if !ctx.check_stability_and_hidden(e) {
             return;
         }
         e.variants(ctx.db)
@@ -257,9 +251,6 @@ impl Completions {
         local_name: hir::Name,
         doc_aliases: Vec<syntax::SmolStr>,
     ) {
-        if !ctx.check_stability(Some(&module.attrs(ctx.db))) {
-            return;
-        }
         self.add_path_resolution(
             ctx,
             path_ctx,
@@ -276,9 +267,6 @@ impl Completions {
         mac: hir::Macro,
         local_name: hir::Name,
     ) {
-        if !ctx.check_stability(Some(&mac.attrs(ctx.db))) {
-            return;
-        }
         let is_private_editable = match ctx.is_visible(&mac) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -302,9 +290,6 @@ impl Completions {
         func: hir::Function,
         local_name: Option<hir::Name>,
     ) {
-        if !ctx.check_stability(Some(&func.attrs(ctx.db))) {
-            return;
-        }
         let is_private_editable = match ctx.is_visible(&func) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -332,9 +317,6 @@ impl Completions {
         receiver: Option<SmolStr>,
         local_name: Option<hir::Name>,
     ) {
-        if !ctx.check_stability(Some(&func.attrs(ctx.db))) {
-            return;
-        }
         let is_private_editable = match ctx.is_visible(&func) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -362,9 +344,6 @@ impl Completions {
         func: hir::Function,
         import: LocatedImport,
     ) {
-        if !ctx.check_stability(Some(&func.attrs(ctx.db))) {
-            return;
-        }
         let is_private_editable = match ctx.is_visible(&func) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -387,9 +366,6 @@ impl Completions {
     }
 
     pub(crate) fn add_const(&mut self, ctx: &CompletionContext<'_>, konst: hir::Const) {
-        if !ctx.check_stability(Some(&konst.attrs(ctx.db))) {
-            return;
-        }
         let is_private_editable = match ctx.is_visible(&konst) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -406,9 +382,6 @@ impl Completions {
         ctx: &CompletionContext<'_>,
         type_alias: hir::TypeAlias,
     ) {
-        if !ctx.check_stability(Some(&type_alias.attrs(ctx.db))) {
-            return;
-        }
         let is_private_editable = match ctx.is_visible(&type_alias) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -438,7 +411,7 @@ impl Completions {
         variant: hir::Variant,
         path: hir::ModPath,
     ) {
-        if !ctx.check_stability(Some(&variant.attrs(ctx.db))) {
+        if !ctx.check_stability_and_hidden(variant) {
             return;
         }
         if let Some(builder) =
@@ -455,7 +428,7 @@ impl Completions {
         variant: hir::Variant,
         local_name: Option<hir::Name>,
     ) {
-        if !ctx.check_stability(Some(&variant.attrs(ctx.db))) {
+        if !ctx.check_stability_and_hidden(variant) {
             return;
         }
         if let PathCompletionCtx { kind: PathKind::Pat { pat_ctx }, .. } = path_ctx {
@@ -479,9 +452,6 @@ impl Completions {
         field: hir::Field,
         ty: &hir::Type,
     ) {
-        if !ctx.check_stability(Some(&field.attrs(ctx.db))) {
-            return;
-        }
         let is_private_editable = match ctx.is_visible(&field) {
             Visible::Yes => false,
             Visible::Editable => true,
@@ -506,12 +476,18 @@ impl Completions {
         path: Option<hir::ModPath>,
         local_name: Option<hir::Name>,
     ) {
-        if !ctx.check_stability(Some(&strukt.attrs(ctx.db))) {
-            return;
-        }
-        if let Some(builder) =
-            render_struct_literal(RenderContext::new(ctx), path_ctx, strukt, path, local_name)
-        {
+        let is_private_editable = match ctx.is_visible(&strukt) {
+            Visible::Yes => false,
+            Visible::Editable => true,
+            Visible::No => return,
+        };
+        if let Some(builder) = render_struct_literal(
+            RenderContext::new(ctx).private_editable(is_private_editable),
+            path_ctx,
+            strukt,
+            path,
+            local_name,
+        ) {
             self.add(builder.build(ctx.db));
         }
     }
@@ -523,10 +499,17 @@ impl Completions {
         path: Option<hir::ModPath>,
         local_name: Option<hir::Name>,
     ) {
-        if !ctx.check_stability(Some(&un.attrs(ctx.db))) {
-            return;
-        }
-        let item = render_union_literal(RenderContext::new(ctx), un, path, local_name);
+        let is_private_editable = match ctx.is_visible(&un) {
+            Visible::Yes => false,
+            Visible::Editable => true,
+            Visible::No => return,
+        };
+        let item = render_union_literal(
+            RenderContext::new(ctx).private_editable(is_private_editable),
+            un,
+            path,
+            local_name,
+        );
         self.add_opt(item);
     }
 
@@ -571,7 +554,7 @@ impl Completions {
         variant: hir::Variant,
         local_name: Option<hir::Name>,
     ) {
-        if !ctx.check_stability(Some(&variant.attrs(ctx.db))) {
+        if !ctx.check_stability_and_hidden(variant) {
             return;
         }
         self.add_opt(render_variant_pat(
@@ -591,7 +574,7 @@ impl Completions {
         variant: hir::Variant,
         path: hir::ModPath,
     ) {
-        if !ctx.check_stability(Some(&variant.attrs(ctx.db))) {
+        if !ctx.check_stability_and_hidden(variant) {
             return;
         }
         let path = Some(&path);
@@ -612,10 +595,17 @@ impl Completions {
         strukt: hir::Struct,
         local_name: Option<hir::Name>,
     ) {
-        if !ctx.check_stability(Some(&strukt.attrs(ctx.db))) {
-            return;
-        }
-        self.add_opt(render_struct_pat(RenderContext::new(ctx), pattern_ctx, strukt, local_name));
+        let is_private_editable = match ctx.is_visible(&strukt) {
+            Visible::Yes => false,
+            Visible::Editable => true,
+            Visible::No => return,
+        };
+        self.add_opt(render_struct_pat(
+            RenderContext::new(ctx).private_editable(is_private_editable),
+            pattern_ctx,
+            strukt,
+            local_name,
+        ));
     }
 
     pub(crate) fn suggest_name(&mut self, ctx: &CompletionContext<'_>, name: &str) {
@@ -660,7 +650,7 @@ fn enum_variants_with_paths(
         if let Some(path) = ctx.module.find_path(
             ctx.db,
             hir::ModuleDef::from(variant),
-            ctx.config.import_path_config(),
+            ctx.config.import_path_config(ctx.is_nightly),
         ) {
             // Variants with trivial paths are already added by the existing completion logic,
             // so we should avoid adding these twice
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
index 7679d9076ded2..d12654665ce95 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
@@ -42,31 +42,38 @@ pub(crate) fn complete_dot(
         item.detail("expr.await");
         item.add_to(acc, ctx.db);
 
-        // Completions that skip `.await`, e.g. `.await.foo()`.
-        let dot_access_kind = match &dot_access.kind {
-            DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
-                DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
-            }
-            it @ DotAccessKind::Method { .. } => *it,
-        };
-        let dot_access = DotAccess {
-            receiver: dot_access.receiver.clone(),
-            receiver_ty: Some(hir::TypeInfo { original: future_output.clone(), adjusted: None }),
-            kind: dot_access_kind,
-            ctx: dot_access.ctx,
-        };
-        complete_fields(
-            acc,
-            ctx,
-            &future_output,
-            |acc, field, ty| acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty),
-            |acc, field, ty| acc.add_tuple_field(ctx, Some(await_str.clone()), field, &ty),
-            is_field_access,
-            is_method_access_with_parens,
-        );
-        complete_methods(ctx, &future_output, &traits_in_scope, |func| {
-            acc.add_method(ctx, &dot_access, func, Some(await_str.clone()), None)
-        });
+        if ctx.config.enable_auto_await {
+            // Completions that skip `.await`, e.g. `.await.foo()`.
+            let dot_access_kind = match &dot_access.kind {
+                DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
+                    DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
+                }
+                it @ DotAccessKind::Method { .. } => *it,
+            };
+            let dot_access = DotAccess {
+                receiver: dot_access.receiver.clone(),
+                receiver_ty: Some(hir::TypeInfo {
+                    original: future_output.clone(),
+                    adjusted: None,
+                }),
+                kind: dot_access_kind,
+                ctx: dot_access.ctx,
+            };
+            complete_fields(
+                acc,
+                ctx,
+                &future_output,
+                |acc, field, ty| {
+                    acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty)
+                },
+                |acc, field, ty| acc.add_tuple_field(ctx, Some(await_str.clone()), field, &ty),
+                is_field_access,
+                is_method_access_with_parens,
+            );
+            complete_methods(ctx, &future_output, &traits_in_scope, |func| {
+                acc.add_method(ctx, &dot_access, func, Some(await_str.clone()), None)
+            });
+        }
     }
 
     complete_fields(
@@ -82,39 +89,41 @@ pub(crate) fn complete_dot(
         acc.add_method(ctx, dot_access, func, None, None)
     });
 
-    // FIXME:
-    // Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
-    // its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
-    // Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
-    let iter = receiver_ty
-        .strip_references()
-        .add_reference(hir::Mutability::Shared)
-        .into_iterator_iter(ctx.db)
-        .map(|ty| (ty, SmolStr::new_static("iter()")));
-    // Does <receiver_ty as IntoIterator>::IntoIter` exist?
-    let into_iter = || {
-        receiver_ty
-            .clone()
+    if ctx.config.enable_auto_iter {
+        // FIXME:
+        // Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
+        // its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
+        // Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
+        let iter = receiver_ty
+            .strip_references()
+            .add_reference(hir::Mutability::Shared)
             .into_iterator_iter(ctx.db)
-            .map(|ty| (ty, SmolStr::new_static("into_iter()")))
-    };
-    if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
-        // Skip iterators, e.g. complete `.iter().filter_map()`.
-        let dot_access_kind = match &dot_access.kind {
-            DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
-                DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
-            }
-            it @ DotAccessKind::Method { .. } => *it,
+            .map(|ty| (ty, SmolStr::new_static("iter()")));
+        // Does <receiver_ty as IntoIterator>::IntoIter` exist?
+        let into_iter = || {
+            receiver_ty
+                .clone()
+                .into_iterator_iter(ctx.db)
+                .map(|ty| (ty, SmolStr::new_static("into_iter()")))
         };
-        let dot_access = DotAccess {
-            receiver: dot_access.receiver.clone(),
-            receiver_ty: Some(hir::TypeInfo { original: iter.clone(), adjusted: None }),
-            kind: dot_access_kind,
-            ctx: dot_access.ctx,
-        };
-        complete_methods(ctx, &iter, &traits_in_scope, |func| {
-            acc.add_method(ctx, &dot_access, func, Some(iter_sym.clone()), None)
-        });
+        if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
+            // Skip iterators, e.g. complete `.iter().filter_map()`.
+            let dot_access_kind = match &dot_access.kind {
+                DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
+                    DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
+                }
+                it @ DotAccessKind::Method { .. } => *it,
+            };
+            let dot_access = DotAccess {
+                receiver: dot_access.receiver.clone(),
+                receiver_ty: Some(hir::TypeInfo { original: iter.clone(), adjusted: None }),
+                kind: dot_access_kind,
+                ctx: dot_access.ctx,
+            };
+            complete_methods(ctx, &iter, &traits_in_scope, |func| {
+                acc.add_method(ctx, &dot_access, func, Some(iter_sym.clone()), None)
+            });
+        }
     }
 }
 
@@ -1466,4 +1475,34 @@ async fn bar() {
 "#,
         );
     }
+
+    #[test]
+    fn receiver_without_deref_impl_completion() {
+        check_no_kw(
+            r#"
+//- minicore: receiver
+use core::ops::Receiver;
+
+struct Foo;
+
+impl Foo {
+    fn foo(self: Bar) {}
+}
+
+struct Bar;
+
+impl Receiver for Bar {
+    type Target = Foo;
+}
+
+fn main() {
+    let bar = Bar;
+    bar.$0
+}
+"#,
+            expect![[r#"
+    me foo() fn(self: Bar)
+"#]],
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index db18b531d7c3c..e710175170199 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -247,7 +247,7 @@ pub(crate) fn complete_expr_path(
                             .find_path(
                                 ctx.db,
                                 hir::ModuleDef::from(strukt),
-                                ctx.config.import_path_config(),
+                                ctx.config.import_path_config(ctx.is_nightly),
                             )
                             .filter(|it| it.len() > 1);
 
@@ -269,7 +269,7 @@ pub(crate) fn complete_expr_path(
                             .find_path(
                                 ctx.db,
                                 hir::ModuleDef::from(un),
-                                ctx.config.import_path_config(),
+                                ctx.config.import_path_config(ctx.is_nightly),
                             )
                             .filter(|it| it.len() > 1);
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
index 73313eeaa6b79..24243f57b46a0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
@@ -5,7 +5,7 @@ use ide_db::imports::{
     insert_use::ImportScope,
 };
 use itertools::Itertools;
-use syntax::{ast, AstNode, SyntaxNode, ToSmolStr};
+use syntax::{ast, AstNode, SyntaxNode};
 
 use crate::{
     config::AutoImportExclusionType,
@@ -257,7 +257,7 @@ fn import_on_the_fly(
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
 
-    let import_cfg = ctx.config.import_path_config();
+    let import_cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     import_assets
         .search_for_imports(&ctx.sema, import_cfg, ctx.config.insert_use.prefix_kind)
@@ -316,7 +316,7 @@ fn import_on_the_fly_pat_(
         ItemInNs::Values(def) => matches!(def, hir::ModuleDef::Const(_)),
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     import_assets
         .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
@@ -358,7 +358,7 @@ fn import_on_the_fly_method(
 
     let user_input_lowercased = potential_import_name.to_lowercase();
 
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     import_assets
         .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
@@ -444,7 +444,7 @@ fn compute_fuzzy_completion_order_key(
     cov_mark::hit!(certain_fuzzy_order_test);
     let import_name = match proposed_mod_path.segments().last() {
         // FIXME: nasty alloc, this is a hot path!
-        Some(name) => name.unescaped().display_no_db().to_smolstr().to_ascii_lowercase(),
+        Some(name) => name.as_str().to_ascii_lowercase(),
         None => return usize::MAX,
     };
     match import_name.match_indices(user_input_lowercased).next() {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 6d1945c45341d..831f5665f4aa0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -31,7 +31,7 @@
 //! }
 //! ```
 
-use hir::{db::ExpandDatabase, HasAttrs, MacroFileId, Name};
+use hir::{db::ExpandDatabase, MacroFileId, Name};
 use ide_db::text_edit::TextEdit;
 use ide_db::{
     documentation::HasDocs, path_transform::PathTransform,
@@ -85,7 +85,7 @@ fn complete_trait_impl_name(
     name: &Option<ast::Name>,
     kind: ImplCompletionKind,
 ) -> Option<()> {
-    let item = match name {
+    let macro_file_item = match name {
         Some(name) => name.syntax().parent(),
         None => {
             let token = &ctx.token;
@@ -96,12 +96,12 @@ fn complete_trait_impl_name(
             .parent()
         }
     }?;
-    let item = ctx.sema.original_syntax_node_rooted(&item)?;
+    let real_file_item = ctx.sema.original_syntax_node_rooted(&macro_file_item)?;
     // item -> ASSOC_ITEM_LIST -> IMPL
-    let impl_def = ast::Impl::cast(item.parent()?.parent()?)?;
+    let impl_def = ast::Impl::cast(macro_file_item.parent()?.parent()?)?;
     let replacement_range = {
         // ctx.sema.original_ast_node(item)?;
-        let first_child = item
+        let first_child = real_file_item
             .children_with_tokens()
             .find(|child| {
                 !matches!(
@@ -109,7 +109,7 @@ fn complete_trait_impl_name(
                     SyntaxKind::COMMENT | SyntaxKind::WHITESPACE | SyntaxKind::ATTR
                 )
             })
-            .unwrap_or_else(|| SyntaxElement::Node(item.clone()));
+            .unwrap_or_else(|| SyntaxElement::Node(real_file_item.clone()));
 
         TextRange::new(first_child.text_range().start(), ctx.source_range().end())
     };
@@ -133,8 +133,11 @@ pub(crate) fn complete_trait_impl_item_by_name(
             acc,
             ctx,
             ImplCompletionKind::All,
-            match name_ref {
-                Some(name) => name.syntax().text_range(),
+            match name_ref
+                .as_ref()
+                .and_then(|name| ctx.sema.original_syntax_node_rooted(name.syntax()))
+            {
+                Some(name) => name.text_range(),
                 None => ctx.source_range(),
             },
             impl_,
@@ -152,7 +155,7 @@ fn complete_trait_impl(
     if let Some(hir_impl) = ctx.sema.to_def(impl_def) {
         get_missing_assoc_items(&ctx.sema, impl_def)
             .into_iter()
-            .filter(|item| ctx.check_stability(Some(&item.attrs(ctx.db))))
+            .filter(|item| ctx.check_stability_and_hidden(*item))
             .for_each(|item| {
                 use self::ImplCompletionKind::*;
                 match (item, kind) {
@@ -359,7 +362,7 @@ fn add_type_alias_impl(
     type_alias: hir::TypeAlias,
     impl_def: hir::Impl,
 ) {
-    let alias_name = type_alias.name(ctx.db).unescaped().display(ctx.db).to_smolstr();
+    let alias_name = type_alias.name(ctx.db).as_str().to_smolstr();
 
     let label = format_smolstr!("type {alias_name} =");
 
@@ -516,7 +519,7 @@ fn function_declaration(
 mod tests {
     use expect_test::expect;
 
-    use crate::tests::{check_edit, check_no_kw};
+    use crate::tests::{check, check_edit, check_no_kw};
 
     #[test]
     fn no_completion_inside_fn() {
@@ -1639,4 +1642,51 @@ impl DesugaredAsyncTrait for () {
 "#,
         );
     }
+
+    #[test]
+    fn within_attr_macro() {
+        check(
+            r#"
+//- proc_macros: identity
+trait Trait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+#[proc_macros::identity]
+impl Trait for () {
+    f$0
+}
+                "#,
+            expect![[r#"
+                me fn bar(..)
+                me fn baz(..)
+                me fn foo(..)
+                md proc_macros
+                kw crate::
+                kw self::
+            "#]],
+        );
+        check(
+            r#"
+//- proc_macros: identity
+trait Trait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+#[proc_macros::identity]
+impl Trait for () {
+    fn $0
+}
+        "#,
+            expect![[r#"
+                me fn bar(..)
+                me fn baz(..)
+                me fn foo(..)
+            "#]],
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs
index bafe32942098c..cca6a22f290d2 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs
@@ -7,7 +7,7 @@ use ide_db::{
     base_db::{SourceRootDatabase, VfsPath},
     FxHashSet, RootDatabase, SymbolKind,
 };
-use syntax::{ast, AstNode, SyntaxKind, ToSmolStr};
+use syntax::{ast, AstNode, SyntaxKind};
 
 use crate::{context::CompletionContext, CompletionItem, Completions};
 
@@ -140,9 +140,7 @@ fn directory_to_look_for_submodules(
     module_chain_to_containing_module_file(module, db)
         .into_iter()
         .filter_map(|module| module.name(db))
-        .try_fold(base_directory, |path, name| {
-            path.join(&name.unescaped().display_no_db().to_smolstr())
-        })
+        .try_fold(base_directory, |path, name| path.join(name.as_str()))
 }
 
 fn module_chain_to_containing_module_file(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
index 67ea05e002b73..2c39a8fdfed73 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
@@ -60,7 +60,7 @@ pub(crate) fn complete_postfix(
         None => return,
     };
 
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
         if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
index 9d62622add206..b384987c51ce1 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
@@ -52,8 +52,14 @@ pub(crate) fn complete_use_path(
                         )
                     };
                     for (name, def) in module_scope {
-                        if !ctx.check_stability(def.attrs(ctx.db).as_deref()) {
-                            continue;
+                        if let (Some(attrs), Some(defining_crate)) =
+                            (def.attrs(ctx.db), def.krate(ctx.db))
+                        {
+                            if !ctx.check_stability(Some(&attrs))
+                                || ctx.is_doc_hidden(&attrs, defining_crate)
+                            {
+                                continue;
+                            }
                         }
                         let is_name_already_imported =
                             already_imported_names.contains(name.as_str());
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
index 8b1ce11e8a45f..45aab38e8ea09 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
@@ -14,6 +14,8 @@ pub struct CompletionConfig<'a> {
     pub enable_postfix_completions: bool,
     pub enable_imports_on_the_fly: bool,
     pub enable_self_on_the_fly: bool,
+    pub enable_auto_iter: bool,
+    pub enable_auto_await: bool,
     pub enable_private_editable: bool,
     pub enable_term_search: bool,
     pub term_search_fuel: u64,
@@ -57,11 +59,12 @@ impl CompletionConfig<'_> {
             .flat_map(|snip| snip.prefix_triggers.iter().map(move |trigger| (&**trigger, snip)))
     }
 
-    pub fn import_path_config(&self) -> ImportPathConfig {
+    pub fn import_path_config(&self, allow_unstable: bool) -> ImportPathConfig {
         ImportPathConfig {
             prefer_no_std: self.prefer_no_std,
             prefer_prelude: self.prefer_prelude,
             prefer_absolute: self.prefer_absolute,
+            allow_unstable,
         }
     }
 }
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 3a2a4a23a1987..2f1860cbb59af 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -443,7 +443,9 @@ pub(crate) struct CompletionContext<'a> {
     /// The module of the `scope`.
     pub(crate) module: hir::Module,
     /// Whether nightly toolchain is used. Cached since this is looked up a lot.
-    is_nightly: bool,
+    pub(crate) is_nightly: bool,
+    /// The edition of the current crate
+    // FIXME: This should probably be the crate of the current token?
     pub(crate) edition: Edition,
 
     /// The expected name of what we are completing.
@@ -532,7 +534,7 @@ impl CompletionContext<'_> {
         }
     }
 
-    /// Checks if an item is visible and not `doc(hidden)` at the completion site.
+    /// Checks if an item is visible, not `doc(hidden)` and stable at the completion site.
     pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
     where
         I: hir::HasVisibility + hir::HasAttrs + hir::HasCrate + Copy,
@@ -568,6 +570,15 @@ impl CompletionContext<'_> {
         !attrs.is_unstable() || self.is_nightly
     }
 
+    pub(crate) fn check_stability_and_hidden<I>(&self, item: I) -> bool
+    where
+        I: hir::HasAttrs + hir::HasCrate,
+    {
+        let defining_crate = item.krate(self.db);
+        let attrs = item.attrs(self.db);
+        self.check_stability(Some(&attrs)) && !self.is_doc_hidden(&attrs, defining_crate)
+    }
+
     /// Whether the given trait is an operator trait or not.
     pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
         match trait_.attrs(self.db).lang() {
@@ -645,6 +656,10 @@ impl CompletionContext<'_> {
         attrs: &hir::Attrs,
         defining_crate: hir::Crate,
     ) -> Visible {
+        if !self.check_stability(Some(attrs)) {
+            return Visible::No;
+        }
+
         if !vis.is_visible_from(self.db, self.module.into()) {
             if !self.config.enable_private_editable {
                 return Visible::No;
@@ -664,7 +679,7 @@ impl CompletionContext<'_> {
         }
     }
 
-    fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
+    pub(crate) fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
         // `doc(hidden)` items are only completed within the defining crate.
         self.krate != defining_crate && attrs.has_doc_hidden()
     }
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 3c4d489c0ff88..f5a50ae81907f 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
@@ -5,7 +5,7 @@ use hir::{ExpandResult, Semantics, Type, TypeInfo, Variant};
 use ide_db::{active_parameter::ActiveParameter, RootDatabase};
 use itertools::Either;
 use syntax::{
-    algo::{ancestors_at_offset, find_node_at_offset, non_trivia_sibling},
+    algo::{self, ancestors_at_offset, find_node_at_offset, non_trivia_sibling},
     ast::{
         self, AttrKind, HasArgList, HasGenericArgs, HasGenericParams, HasLoopBody, HasName,
         NameOrNameRef,
@@ -85,6 +85,11 @@ pub(super) fn expand_and_analyze(
     })
 }
 
+fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Option<SyntaxToken> {
+    let token = file.token_at_offset(offset).left_biased()?;
+    algo::skip_whitespace_token(token, Direction::Prev)
+}
+
 /// Expand attributes and macro calls at the current cursor position for both the original file
 /// and fake file repeatedly. As soon as one of the two expansions fail we stop so the original
 /// and speculative states stay in sync.
@@ -125,9 +130,7 @@ fn expand(
 
     // Left biased since there may already be an identifier token there, and we appended to it.
     if !sema.might_be_inside_macro_call(&fake_ident_token)
-        && original_file
-            .token_at_offset(original_offset + relative_offset)
-            .left_biased()
+        && token_at_offset_ignore_whitespace(&original_file, original_offset + relative_offset)
             .is_some_and(|original_token| !sema.might_be_inside_macro_call(&original_token))
     {
         // Recursion base case.
@@ -143,9 +146,11 @@ fn expand(
 
     let parent_item =
         |item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
+    let original_node = token_at_offset_ignore_whitespace(&original_file, original_offset)
+        .and_then(|token| token.parent_ancestors().find_map(ast::Item::cast));
     let ancestor_items = iter::successors(
         Option::zip(
-            find_node_at_offset::<ast::Item>(&original_file, original_offset),
+            original_node,
             find_node_at_offset::<ast::Item>(
                 &speculative_file,
                 fake_ident_token.text_range().start(),
@@ -1590,11 +1595,11 @@ fn pattern_context_for(
                                         }).map(|enum_| enum_.variants(sema.db))
                                     })
                                 }).map(|variants| variants.iter().filter_map(|variant| {
-                                        let variant_name = variant.name(sema.db).unescaped().display(sema.db).to_string();
+                                        let variant_name = variant.name(sema.db);
 
                                         let variant_already_present = match_arm_list.arms().any(|arm| {
                                             arm.pat().and_then(|pat| {
-                                                let pat_already_present = pat.syntax().to_string().contains(&variant_name);
+                                                let pat_already_present = pat.syntax().to_string().contains(variant_name.as_str());
                                                 pat_already_present.then_some(pat_already_present)
                                             }).is_some()
                                         });
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index dc2f9a7680293..41a82409597bd 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -82,8 +82,7 @@ pub struct CompletionItem {
     pub ref_match: Option<(CompletionItemRefMode, TextSize)>,
 
     /// The import data to add to completion's edits.
-    /// (ImportPath, LastSegment)
-    pub import_to_add: SmallVec<[(String, String); 1]>,
+    pub import_to_add: SmallVec<[String; 1]>,
 }
 
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
@@ -181,6 +180,8 @@ pub struct CompletionRelevance {
     pub postfix_match: Option<CompletionRelevancePostfixMatch>,
     /// This is set for items that are function (associated or method)
     pub function: Option<CompletionRelevanceFn>,
+    /// true when there is an `await.method()` or `iter().method()` completion.
+    pub is_skipping_completion: bool,
 }
 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
 pub struct CompletionRelevanceTraitInfo {
@@ -269,6 +270,7 @@ impl CompletionRelevance {
             postfix_match,
             trait_,
             function,
+            is_skipping_completion,
         } = self;
 
         // only applicable for completions within use items
@@ -296,6 +298,12 @@ impl CompletionRelevance {
                 score -= 5;
             }
         }
+
+        // Lower rank for completions that skip `await` and `iter()`.
+        if is_skipping_completion {
+            score -= 7;
+        }
+
         // lower rank for items that need an import
         if requires_import {
             score -= 1;
@@ -561,12 +569,7 @@ impl Builder {
         let import_to_add = self
             .imports_to_add
             .into_iter()
-            .filter_map(|import| {
-                Some((
-                    import.import_path.display(db, self.edition).to_string(),
-                    import.import_path.segments().last()?.display(db, self.edition).to_string(),
-                ))
-            })
+            .map(|import| import.import_path.display(db, self.edition).to_string())
             .collect();
 
         CompletionItem {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
index 56d7eeaf8ea03..8051d48ca5fe0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -10,17 +10,13 @@ mod snippet;
 #[cfg(test)]
 mod tests;
 
-use ide_db::text_edit::TextEdit;
 use ide_db::{
-    helpers::mod_path_to_ast,
-    imports::{
-        import_assets::NameToImport,
-        insert_use::{self, ImportScope},
-    },
-    items_locator,
+    imports::insert_use::{self, ImportScope},
     syntax_helpers::tree_diff::diff,
+    text_edit::TextEdit,
     FilePosition, FxHashSet, RootDatabase,
 };
+use syntax::ast::make;
 
 use crate::{
     completions::Completions,
@@ -272,7 +268,7 @@ pub fn resolve_completion_edits(
     db: &RootDatabase,
     config: &CompletionConfig<'_>,
     FilePosition { file_id, offset }: FilePosition,
-    imports: impl IntoIterator<Item = (String, String)>,
+    imports: impl IntoIterator<Item = String>,
 ) -> Option<Vec<TextEdit>> {
     let _p = tracing::info_span!("resolve_completion_edits").entered();
     let sema = hir::Semantics::new(db);
@@ -289,27 +285,12 @@ pub fn resolve_completion_edits(
     let new_ast = scope.clone_for_update();
     let mut import_insert = TextEdit::builder();
 
-    let cfg = config.import_path_config();
-
-    imports.into_iter().for_each(|(full_import_path, imported_name)| {
-        let items_with_name = items_locator::items_with_name(
-            &sema,
-            current_crate,
-            NameToImport::exact_case_sensitive(imported_name),
-            items_locator::AssocSearchMode::Include,
+    imports.into_iter().for_each(|full_import_path| {
+        insert_use::insert_use(
+            &new_ast,
+            make::path_from_text_with_edition(&full_import_path, current_edition),
+            &config.insert_use,
         );
-        let import = items_with_name
-            .filter_map(|candidate| {
-                current_module.find_use_path(db, candidate, config.insert_use.prefix_kind, cfg)
-            })
-            .find(|mod_path| mod_path.display(db, current_edition).to_string() == full_import_path);
-        if let Some(import_path) = import {
-            insert_use::insert_use(
-                &new_ast,
-                mod_path_to_ast(&import_path, current_edition),
-                &config.insert_use,
-            );
-        }
     });
 
     diff(scope.as_syntax_node(), new_ast.as_syntax_node()).into_text_edit(&mut import_insert);
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 61e8114d381aa..dc7eacbfbafdb 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -130,10 +130,8 @@ pub(crate) fn render_field(
     let db = ctx.db();
     let is_deprecated = ctx.is_deprecated(field);
     let name = field.name(db);
-    let (name, escaped_name) = (
-        name.unescaped().display(db).to_smolstr(),
-        name.display_no_db(ctx.completion.edition).to_smolstr(),
-    );
+    let (name, escaped_name) =
+        (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr());
     let mut item = CompletionItem::new(
         SymbolKind::Field,
         ctx.source_range(),
@@ -142,7 +140,8 @@ pub(crate) fn render_field(
     );
     item.set_relevance(CompletionRelevance {
         type_match: compute_type_match(ctx.completion, ty),
-        exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
+        exact_name_match: compute_exact_name_match(ctx.completion, &name),
+        is_skipping_completion: receiver.is_some(),
         ..CompletionRelevance::default()
     });
     item.detail(ty.display(db, ctx.completion.edition).to_string())
@@ -215,6 +214,10 @@ pub(crate) fn render_tuple_field(
     );
     item.detail(ty.display(ctx.db(), ctx.completion.edition).to_string())
         .lookup_by(field.to_string());
+    item.set_relevance(CompletionRelevance {
+        is_skipping_completion: receiver.is_some(),
+        ..ctx.completion_relevance()
+    });
     item.build(ctx.db())
 }
 
@@ -298,7 +301,7 @@ pub(crate) fn render_expr(
             .unwrap_or_else(|| String::from("..."))
     };
 
-    let cfg = ctx.config.import_path_config();
+    let cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.edition).ok()?;
 
@@ -512,7 +515,7 @@ fn render_resolution_simple_(
     let mut item = CompletionItem::new(
         kind,
         ctx.source_range(),
-        local_name.unescaped().display(db).to_smolstr(),
+        local_name.as_str().to_smolstr(),
         ctx.completion.edition,
     );
     item.set_relevance(ctx.completion_relevance())
@@ -1335,6 +1338,7 @@ fn main() { let _: m::Spam = S$0 }
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
+                            is_skipping_completion: false,
                         },
                         trigger_call_info: true,
                     },
@@ -1364,6 +1368,7 @@ fn main() { let _: m::Spam = S$0 }
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
+                            is_skipping_completion: false,
                         },
                         trigger_call_info: true,
                     },
@@ -1453,6 +1458,7 @@ fn foo() { A { the$0 } }
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
+                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -1511,6 +1517,7 @@ impl S {
                                     return_type: Other,
                                 },
                             ),
+                            is_skipping_completion: false,
                         },
                     },
                     CompletionItem {
@@ -1653,6 +1660,7 @@ fn foo(s: S) { s.$0 }
                                     return_type: Other,
                                 },
                             ),
+                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -1864,6 +1872,7 @@ fn f() -> i32 {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
+                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -2624,6 +2633,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
                                     return_type: Other,
                                 },
                             ),
+                            is_skipping_completion: false,
                         },
                         ref_match: "&@107",
                     },
@@ -2709,6 +2719,7 @@ fn foo() {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
+                            is_skipping_completion: false,
                         },
                     },
                 ]
@@ -2766,6 +2777,7 @@ fn main() {
                                     return_type: Other,
                                 },
                             ),
+                            is_skipping_completion: false,
                         },
                         ref_match: "&@92",
                     },
@@ -3140,6 +3152,7 @@ fn main() {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
+                            is_skipping_completion: false,
                         },
                     },
                     CompletionItem {
@@ -3173,6 +3186,7 @@ fn main() {
                             is_private_editable: false,
                             postfix_match: None,
                             function: None,
+                            is_skipping_completion: false,
                         },
                     },
                 ]
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs
index 415d87c6239b4..e357ab24d22df 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs
@@ -14,10 +14,8 @@ pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option
 fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
     let db = ctx.db();
     let name = const_.name(db)?;
-    let (name, escaped_name) = (
-        name.unescaped().display(db).to_smolstr(),
-        name.display(db, ctx.completion.edition).to_smolstr(),
-    );
+    let (name, escaped_name) =
+        (name.as_str().to_smolstr(), name.display(db, ctx.completion.edition).to_smolstr());
     let detail = const_.display(db, ctx.completion.edition).to_string();
 
     let mut item =
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
index 3b97d67169eca..c3354902c3b78 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
@@ -59,13 +59,10 @@ fn render(
 
     let (call, escaped_call) = match &func_kind {
         FuncKind::Method(_, Some(receiver)) => (
-            format_smolstr!("{}.{}", receiver, name.unescaped().display(ctx.db())),
+            format_smolstr!("{}.{}", receiver, name.as_str()),
             format_smolstr!("{}.{}", receiver, name.display(ctx.db(), completion.edition)),
         ),
-        _ => (
-            name.unescaped().display(db).to_smolstr(),
-            name.display(db, completion.edition).to_smolstr(),
-        ),
+        _ => (name.as_str().to_smolstr(), name.display(db, completion.edition).to_smolstr()),
     };
     let has_self_param = func.self_param(db).is_some();
     let mut item = CompletionItem::new(
@@ -126,6 +123,7 @@ fn render(
         exact_name_match: compute_exact_name_match(completion, &call),
         function,
         trait_: trait_info,
+        is_skipping_completion: matches!(func_kind, FuncKind::Method(_, Some(_))),
         ..ctx.completion_relevance()
     });
 
@@ -151,7 +149,7 @@ fn render(
     item.set_documentation(ctx.docs(func))
         .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
         .detail(detail)
-        .lookup_by(name.unescaped().display(db).to_smolstr());
+        .lookup_by(name.as_str().to_smolstr());
 
     if let Some((cap, (self_param, params))) = complete_call_parens {
         add_call_parens(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
index c71356e5300fc..aab54ca5e0146 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
@@ -75,7 +75,7 @@ fn render(
         None => (name.clone().into(), name.into(), false),
     };
     let (qualified_name, escaped_qualified_name) = (
-        qualified_name.unescaped().display(ctx.db()).to_string(),
+        qualified_name.display_verbatim(ctx.db()).to_string(),
         qualified_name.display(ctx.db(), completion.edition).to_string(),
     );
     let snippet_cap = ctx.snippet_cap();
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
index 6490171fbb48b..e265e92f9794b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs
@@ -46,21 +46,19 @@ fn render(
         ctx.source_range()
     };
 
-    let (name, escaped_name) = (
-        name.unescaped().display(ctx.db()).to_smolstr(),
-        name.display(ctx.db(), completion.edition).to_smolstr(),
-    );
+    let (name, escaped_name) =
+        (name.as_str(), name.display(ctx.db(), completion.edition).to_smolstr());
     let docs = ctx.docs(macro_);
     let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default();
     let is_fn_like = macro_.is_fn_like(completion.db);
-    let (bra, ket) = if is_fn_like { guess_macro_braces(&name, docs_str) } else { ("", "") };
+    let (bra, ket) = if is_fn_like { guess_macro_braces(name, docs_str) } else { ("", "") };
 
     let needs_bang = is_fn_like && !is_use_path && !has_macro_bang;
 
     let mut item = CompletionItem::new(
         SymbolKind::from(macro_.kind(completion.db)),
         source_range,
-        label(&ctx, needs_bang, bra, ket, &name),
+        label(&ctx, needs_bang, bra, ket, &name.to_smolstr()),
         completion.edition,
     );
     item.set_deprecated(ctx.is_deprecated(macro_))
@@ -71,11 +69,11 @@ fn render(
     match ctx.snippet_cap() {
         Some(cap) if needs_bang && !has_call_parens => {
             let snippet = format!("{escaped_name}!{bra}$0{ket}");
-            let lookup = banged_name(&name);
+            let lookup = banged_name(name);
             item.insert_snippet(cap, snippet).lookup_by(lookup);
         }
         _ if needs_bang => {
-            item.insert_text(banged_name(&escaped_name)).lookup_by(banged_name(&name));
+            item.insert_text(banged_name(&escaped_name)).lookup_by(banged_name(name));
         }
         _ => {
             cov_mark::hit!(dont_insert_macro_call_parens_unnecessary);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
index 5675dfb5c6ff2..124abb17b6a1c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
@@ -31,13 +31,11 @@ pub(crate) fn render_struct_pat(
     }
 
     let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
-    let (name, escaped_name) = (
-        name.unescaped().display(ctx.db()).to_smolstr(),
-        name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
-    );
+    let (name, escaped_name) =
+        (name.as_str(), name.display(ctx.db(), ctx.completion.edition).to_smolstr());
     let kind = strukt.kind(ctx.db());
-    let label = format_literal_label(name.as_str(), kind, ctx.snippet_cap());
-    let lookup = format_literal_lookup(name.as_str(), kind);
+    let label = format_literal_label(name, kind, ctx.snippet_cap());
+    let lookup = format_literal_lookup(name, kind);
     let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
 
     let db = ctx.db();
@@ -61,13 +59,13 @@ pub(crate) fn render_variant_pat(
 
     let (name, escaped_name) = match path {
         Some(path) => (
-            path.unescaped().display(ctx.db()).to_string().into(),
-            path.display(ctx.db(), ctx.completion.edition).to_string().into(),
+            path.display_verbatim(ctx.db()).to_smolstr(),
+            path.display(ctx.db(), ctx.completion.edition).to_smolstr(),
         ),
         None => {
             let name = local_name.unwrap_or_else(|| variant.name(ctx.db()));
             let it = (
-                name.unescaped().display(ctx.db()).to_smolstr(),
+                name.as_str().to_smolstr(),
                 name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
             );
             it
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs
index 09eb19201c5b0..1b952f31360c2 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs
@@ -32,14 +32,11 @@ fn render(
     let name = type_alias.name(db);
     let (name, escaped_name) = if with_eq {
         (
-            SmolStr::from_iter([&name.unescaped().display(db).to_smolstr(), " = "]),
+            SmolStr::from_iter([&name.as_str().to_smolstr(), " = "]),
             SmolStr::from_iter([&name.display_no_db(ctx.completion.edition).to_smolstr(), " = "]),
         )
     } else {
-        (
-            name.unescaped().display(db).to_smolstr(),
-            name.display_no_db(ctx.completion.edition).to_smolstr(),
-        )
+        (name.as_str().to_smolstr(), name.display_no_db(ctx.completion.edition).to_smolstr())
     };
     let detail = type_alias.display(db, ctx.completion.edition).to_string();
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
index e053e299d903a..742036265211e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
@@ -23,12 +23,12 @@ pub(crate) fn render_union_literal(
 
     let (qualified_name, escaped_qualified_name) = match path {
         Some(p) => (
-            p.unescaped().display(ctx.db()).to_string(),
-            p.display(ctx.db(), ctx.completion.edition).to_string(),
+            p.display_verbatim(ctx.db()).to_smolstr(),
+            p.display(ctx.db(), ctx.completion.edition).to_smolstr(),
         ),
         None => (
-            name.unescaped().display(ctx.db()).to_string(),
-            name.display(ctx.db(), ctx.completion.edition).to_string(),
+            name.as_str().to_smolstr(),
+            name.display(ctx.db(), ctx.completion.edition).to_smolstr(),
         ),
     };
     let label = format_literal_label(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
index 04bb178c658f3..866b83a614603 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
@@ -164,7 +164,7 @@ impl Snippet {
 }
 
 fn import_edits(ctx: &CompletionContext<'_>, requires: &[ModPath]) -> Option<Vec<LocatedImport>> {
-    let import_cfg = ctx.config.import_path_config();
+    let import_cfg = ctx.config.import_path_config(ctx.is_nightly);
 
     let resolve = |import| {
         let item = ctx.scope.resolve_mod_path(import).next()?;
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
index b7dbf0a6306c6..9d91f95eb65b8 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -87,6 +87,8 @@ pub(crate) const TEST_CONFIG: CompletionConfig<'_> = CompletionConfig {
     fields_to_resolve: CompletionFieldsToResolve::empty(),
     exclude_flyimport: vec![],
     exclude_traits: &[],
+    enable_auto_await: true,
+    enable_auto_iter: true,
 };
 
 pub(crate) fn completion_list(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index e117dbf4bdf0b..663a038580d55 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -1965,3 +1965,24 @@ fn bar() {
         "#]],
     );
 }
+
+#[test]
+fn doc_hidden_enum_variant() {
+    check(
+        r#"
+//- /foo.rs crate:foo
+pub enum Enum {
+    #[doc(hidden)] Hidden,
+    Visible,
+}
+
+//- /lib.rs crate:lib deps:foo
+fn foo() {
+    let _ = foo::Enum::$0;
+}
+    "#,
+        expect![[r#"
+            ev Visible Visible
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
index d491e438feffc..2e7c53def7fc5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
@@ -1390,6 +1390,41 @@ pub struct FooStruct {}
     );
 }
 
+#[test]
+fn flyimport_pattern_unstable_path() {
+    check(
+        r#"
+//- /main.rs crate:main deps:std
+fn function() {
+    let foo$0
+}
+//- /std.rs crate:std
+#[unstable]
+pub mod unstable {
+    pub struct FooStruct {}
+}
+"#,
+        expect![""],
+    );
+    check(
+        r#"
+//- toolchain:nightly
+//- /main.rs crate:main deps:std
+fn function() {
+    let foo$0
+}
+//- /std.rs crate:std
+#[unstable]
+pub mod unstable {
+    pub struct FooStruct {}
+}
+"#,
+        expect![[r#"
+            st FooStruct (use std::unstable::FooStruct)
+        "#]],
+    );
+}
+
 #[test]
 fn flyimport_pattern_unstable_item_on_nightly() {
     check(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs
index 04b3a47a64dab..593b1edde5cc5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs
@@ -451,3 +451,20 @@ marco_rules! m { () => {} }
         "#]],
     );
 }
+
+#[test]
+fn use_tree_doc_hidden() {
+    check(
+        r#"
+//- /foo.rs crate:foo
+#[doc(hidden)] pub struct Hidden;
+pub struct Visible;
+
+//- /lib.rs crate:lib deps:foo
+use foo::$0;
+    "#,
+        expect![[r#"
+            st Visible Visible
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
index 49d26dfe25c12..d12bda0816fd3 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -794,7 +794,7 @@ impl NameRefClass {
                                 hir::AssocItem::TypeAlias(it) => Some(it),
                                 _ => None,
                             })
-                            .find(|alias| alias.name(sema.db).eq_ident(name_ref.text().as_str()))
+                            .find(|alias| alias.name(sema.db).as_str() == name_ref.text().trim_start_matches("r#"))
                         {
                             // No substitution, this can only occur in type position.
                             return Some(NameRefClass::Definition(Definition::TypeAlias(ty), None));
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs
index 9e3506d6f53b7..2f4d07446f2c1 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs
@@ -46,6 +46,10 @@ impl FamousDefs<'_, '_> {
         self.find_trait("core:cmp:Ord")
     }
 
+    pub fn core_convert_FromStr(&self) -> Option<Trait> {
+        self.find_trait("core:str:FromStr")
+    }
+
     pub fn core_convert_From(&self) -> Option<Trait> {
         self.find_trait("core:convert:From")
     }
@@ -54,6 +58,14 @@ impl FamousDefs<'_, '_> {
         self.find_trait("core:convert:Into")
     }
 
+    pub fn core_convert_TryFrom(&self) -> Option<Trait> {
+        self.find_trait("core:convert:TryFrom")
+    }
+
+    pub fn core_convert_TryInto(&self) -> Option<Trait> {
+        self.find_trait("core:convert:TryInto")
+    }
+
     pub fn core_convert_Index(&self) -> Option<Trait> {
         self.find_trait("core:ops:Index")
     }
@@ -130,6 +142,13 @@ impl FamousDefs<'_, '_> {
         self.find_macro("core:unimplemented")
     }
 
+    pub fn core_fmt_Display(&self) -> Option<Trait> {
+        self.find_trait("core:fmt:Display")
+    }
+
+    pub fn alloc_string_ToString(&self) -> Option<Trait> {
+        self.find_trait("alloc:string:ToString")
+    }
     pub fn builtin_crates(&self) -> impl Iterator<Item = Crate> {
         IntoIterator::into_iter([
             self.std(),
@@ -202,14 +221,15 @@ impl FamousDefs<'_, '_> {
         for segment in path {
             module = module.children(db).find_map(|child| {
                 let name = child.name(db)?;
-                if name.eq_ident(segment) {
+                if name.as_str() == segment {
                     Some(child)
                 } else {
                     None
                 }
             })?;
         }
-        let def = module.scope(db, None).into_iter().find(|(name, _def)| name.eq_ident(trait_))?.1;
+        let def =
+            module.scope(db, None).into_iter().find(|(name, _def)| name.as_str() == trait_)?.1;
         Some(def)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index a045c22c2dff1..f045e44dd318b 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -319,6 +319,7 @@ impl Ctx<'_> {
                                 prefer_no_std: false,
                                 prefer_prelude: true,
                                 prefer_absolute: false,
+                                allow_unstable: true,
                             };
                             let found_path = self.target_module.find_path(
                                 self.source_scope.db.upcast(),
@@ -378,6 +379,7 @@ impl Ctx<'_> {
                     prefer_no_std: false,
                     prefer_prelude: true,
                     prefer_absolute: false,
+                    allow_unstable: true,
                 };
                 let found_path =
                     self.target_module.find_path(self.source_scope.db.upcast(), def, cfg)?;
@@ -417,6 +419,7 @@ impl Ctx<'_> {
                             prefer_no_std: false,
                             prefer_prelude: true,
                             prefer_absolute: false,
+                            allow_unstable: true,
                         };
                         let found_path = self.target_module.find_path(
                             self.source_scope.db.upcast(),
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
index 42efbd68e33d3..59914bedde434 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
@@ -263,13 +263,12 @@ fn rename_mod(
         //  - Module has submodules defined in separate files
         let dir_paths = match (is_mod_rs, has_detached_child, module.name(sema.db)) {
             // Go up one level since the anchor is inside the dir we're trying to rename
-            (true, _, Some(mod_name)) => Some((
-                format!("../{}", mod_name.unescaped().display(sema.db)),
-                format!("../{new_name}"),
-            )),
+            (true, _, Some(mod_name)) => {
+                Some((format!("../{}", mod_name.as_str()), format!("../{new_name}")))
+            }
             // The anchor is on the same level as target dir
             (false, true, Some(mod_name)) => {
-                Some((mod_name.unescaped().display(sema.db).to_string(), new_name.to_owned()))
+                Some((mod_name.as_str().to_owned(), new_name.to_owned()))
             }
             _ => None,
         };
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index a75aba137be6c..7fc563a424104 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -625,7 +625,7 @@ impl<'a> FindUsages<'a> {
             let _p = tracing::info_span!("collect_possible_aliases").entered();
 
             let db = sema.db;
-            let container_name = container.name(db).unescaped().display(db).to_smolstr();
+            let container_name = container.name(db).as_str().to_smolstr();
             let search_scope = Definition::from(container).search_scope(db);
             let mut seen = FxHashSet::default();
             let mut completed = FxHashSet::default();
@@ -925,12 +925,8 @@ impl<'a> FindUsages<'a> {
                             .or_else(|| ty.as_builtin().map(|builtin| builtin.name()))
                     })
                 };
-                // We need to unescape the name in case it is written without "r#" in earlier
-                // editions of Rust where it isn't a keyword.
-                self.def
-                    .name(sema.db)
-                    .or_else(self_kw_refs)
-                    .map(|it| it.unescaped().display(sema.db).to_smolstr())
+                // We need to search without the `r#`, hence `as_str` access.
+                self.def.name(sema.db).or_else(self_kw_refs).map(|it| it.as_str().to_smolstr())
             }
         };
         let name = match &name {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
index c94644eeb89be..e5ce10a771ef9 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
@@ -143,7 +143,7 @@ fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Ar
 fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> {
     let _p = tracing::info_span!("module_symbols").entered();
 
-    Arc::new(SymbolIndex::new(SymbolCollector::collect_module(db.upcast(), module)))
+    Arc::new(SymbolIndex::new(SymbolCollector::new_module(db.upcast(), module)))
 }
 
 pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> {
@@ -284,13 +284,15 @@ impl SymbolIndex {
             builder.insert(key, value).unwrap();
         }
 
-        // FIXME: fst::Map should ideally have a way to shrink the backing buffer without the unwrap dance
-        let map = fst::Map::new({
-            let mut buf = builder.into_inner().unwrap();
-            buf.shrink_to_fit();
-            buf
-        })
-        .unwrap();
+        let map = builder
+            .into_inner()
+            .and_then(|mut buf| {
+                fst::Map::new({
+                    buf.shrink_to_fit();
+                    buf
+                })
+            })
+            .unwrap();
         SymbolIndex { symbols, map }
     }
 
@@ -491,7 +493,7 @@ pub(self) use crate::Trait as IsThisJustATrait;
             .modules(&db)
             .into_iter()
             .map(|module_id| {
-                let mut symbols = SymbolCollector::collect_module(&db, module_id);
+                let mut symbols = SymbolCollector::new_module(&db, module_id);
                 symbols.sort_by_key(|it| it.name.as_str().to_owned());
                 (module_id, symbols)
             })
@@ -518,7 +520,7 @@ struct Duplicate;
             .modules(&db)
             .into_iter()
             .map(|module_id| {
-                let mut symbols = SymbolCollector::collect_module(&db, module_id);
+                let mut symbols = SymbolCollector::new_module(&db, module_id);
                 symbols.sort_by_key(|it| it.name.as_str().to_owned());
                 (module_id, symbols)
             })
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
index 557c95f704b98..0a7141c19b6b5 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
@@ -31,6 +31,12 @@ const USELESS_NAME_PREFIXES: &[&str] = &["from_", "with_", "into_"];
 /// `Result<User, Error>` -> `User`
 const WRAPPER_TYPES: &[&str] = &["Box", "Arc", "Rc", "Option", "Result"];
 
+/// Generic types replaced by a plural of their first argument.
+///
+/// # Examples
+/// `Vec<Name>` -> "names"
+const SEQUENCE_TYPES: &[&str] = &["Vec", "VecDeque", "LinkedList"];
+
 /// Prefixes to strip from methods names
 ///
 /// # Examples
@@ -378,6 +384,11 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<S
             return name_of_type(&inner_ty, db, edition);
         }
 
+        if SEQUENCE_TYPES.contains(&name.as_str()) {
+            let inner_ty = ty.type_arguments().next();
+            return Some(sequence_name(inner_ty.as_ref(), db, edition));
+        }
+
         name
     } else if let Some(trait_) = ty.as_dyn_trait() {
         trait_name(&trait_, db, edition)?
@@ -390,12 +401,32 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<S
         name
     } else if let Some(inner_ty) = ty.remove_ref() {
         return name_of_type(&inner_ty, db, edition);
+    } else if let Some(inner_ty) = ty.as_slice() {
+        return Some(sequence_name(Some(&inner_ty), db, edition));
     } else {
         return None;
     };
     normalize(&name)
 }
 
+fn sequence_name(inner_ty: Option<&hir::Type>, db: &RootDatabase, edition: Edition) -> SmolStr {
+    let items_str = SmolStr::new_static("items");
+    let Some(inner_ty) = inner_ty else {
+        return items_str;
+    };
+    let Some(name) = name_of_type(inner_ty, db, edition) else {
+        return items_str;
+    };
+
+    if name.ends_with(['s', 'x', 'y']) {
+        // Given a type called e.g. "Boss", "Fox" or "Story", don't try to
+        // create a plural.
+        items_str
+    } else {
+        SmolStr::new(format!("{name}s"))
+    }
+}
+
 fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Option<String> {
     let name = trait_.name(db).display(db, edition).to_string();
     if USELESS_TRAITS.contains(&name.as_str()) {
@@ -897,6 +928,58 @@ fn foo() { $0(bar())$0; }
         );
     }
 
+    #[test]
+    fn vec_value() {
+        check(
+            r#"
+struct Vec<T> {};
+struct Seed;
+fn bar() -> Vec<Seed> {}
+fn foo() { $0(bar())$0; }
+"#,
+            "seeds",
+        );
+    }
+
+    #[test]
+    fn vec_value_ends_with_s() {
+        check(
+            r#"
+struct Vec<T> {};
+struct Boss;
+fn bar() -> Vec<Boss> {}
+fn foo() { $0(bar())$0; }
+"#,
+            "items",
+        );
+    }
+
+    #[test]
+    fn vecdeque_value() {
+        check(
+            r#"
+struct VecDeque<T> {};
+struct Seed;
+fn bar() -> VecDeque<Seed> {}
+fn foo() { $0(bar())$0; }
+"#,
+            "seeds",
+        );
+    }
+
+    #[test]
+    fn slice_value() {
+        check(
+            r#"
+struct Vec<T> {};
+struct Seed;
+fn bar() -> &[Seed] {}
+fn foo() { $0(bar())$0; }
+"#,
+            "seeds",
+        );
+    }
+
     #[test]
     fn ref_call() {
         check(
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 535777dfcbea6..7dce95592b819 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -1007,6 +1007,39 @@
                 is_alias: false,
                 is_assoc: false,
             },
+            FileSymbol {
+                name: "ThisStruct",
+                def: Adt(
+                    Struct(
+                        Struct {
+                            id: StructId(
+                                4,
+                            ),
+                        },
+                    ),
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            1,
+                        ),
+                        Edition2021,
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 85..125,
+                    },
+                    name_ptr: AstPtr(
+                        SyntaxNodePtr {
+                            kind: NAME,
+                            range: 115..125,
+                        },
+                    ),
+                },
+                container_name: None,
+                is_alias: false,
+                is_assoc: false,
+            },
         ],
     ),
 ]
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs b/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs
index 515bc418cb467..2fdd8358637df 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/ty_filter.rs
@@ -26,7 +26,7 @@ impl TryEnum {
             _ => return None,
         };
         TryEnum::ALL.iter().find_map(|&var| {
-            if enum_.name(sema.db).eq_ident(var.type_name()) {
+            if enum_.name(sema.db).as_str() == var.type_name() {
                 return Some(var);
             }
             None
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
index dca889d1a8efe..f22041ebe233b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
@@ -147,6 +147,7 @@ pub(crate) fn json_in_items(
                             prefer_no_std: config.prefer_no_std,
                             prefer_prelude: config.prefer_prelude,
                             prefer_absolute: config.prefer_absolute,
+                            allow_unstable: true,
                         };
 
                         if !scope_has("Serialize") {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
index fd1044e51bc23..938b7182bc946 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -128,6 +128,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
                                 prefer_no_std: ctx.config.prefer_no_std,
                                 prefer_prelude: ctx.config.prefer_prelude,
                                 prefer_absolute: ctx.config.prefer_absolute,
+                                allow_unstable: ctx.is_nightly,
                             },
                         )?;
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
index 3ad84f7bda2f2..b023a95fb3559 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -70,6 +70,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
                     prefer_no_std: ctx.config.prefer_no_std,
                     prefer_prelude: ctx.config.prefer_prelude,
                     prefer_absolute: ctx.config.prefer_absolute,
+                    allow_unstable: ctx.is_nightly,
                 },
                 ctx.edition,
             )
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index 13591dfb2eebd..f3109b9bb73a2 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -112,7 +112,7 @@ fn fixes(
                 // shouldn't occur
                 _ => continue 'crates,
             };
-            match current.children.iter().find(|(name, _)| name.eq_ident(seg)) {
+            match current.children.iter().find(|(name, _)| name.as_str() == seg) {
                 Some((_, &child)) => current = &crate_def_map[child],
                 None => continue 'crates,
             }
@@ -161,7 +161,7 @@ fn fixes(
             // try finding a parent that has an inline tree from here on
             let mut current = module;
             for s in stack.iter().rev() {
-                match module.children.iter().find(|(name, _)| name.eq_ident(s)) {
+                match module.children.iter().find(|(name, _)| name.as_str() == s) {
                     Some((_, child)) => {
                         current = &crate_def_map[*child];
                     }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 1e99d7ad6e68a..50c91a69602c1 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -83,7 +83,7 @@ use either::Either;
 use hir::{db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, HirFileId, InFile, Semantics};
 use ide_db::{
     assists::{Assist, AssistId, AssistKind, AssistResolveStrategy},
-    base_db::SourceDatabase,
+    base_db::{ReleaseChannel, SourceDatabase},
     generated::lints::{Lint, LintGroup, CLIPPY_LINT_GROUPS, DEFAULT_LINTS, DEFAULT_LINT_GROUPS},
     imports::insert_use::InsertUseConfig,
     label::Label,
@@ -276,6 +276,7 @@ struct DiagnosticsContext<'a> {
     sema: Semantics<'a, RootDatabase>,
     resolve: &'a AssistResolveStrategy,
     edition: Edition,
+    is_nightly: bool,
 }
 
 impl DiagnosticsContext<'_> {
@@ -368,7 +369,11 @@ pub fn semantic_diagnostics(
 
     let module = sema.file_to_module_def(file_id);
 
-    let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition() };
+    let is_nightly = matches!(
+        module.and_then(|m| db.toolchain_channel(m.krate().into())),
+        Some(ReleaseChannel::Nightly) | None
+    );
+    let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition(), is_nightly };
 
     let mut diags = Vec::new();
     match module {
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
index 4edc3633fbe65..4bead14e31d4d 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -673,6 +673,7 @@ impl Match {
                     prefer_no_std: false,
                     prefer_prelude: true,
                     prefer_absolute: false,
+                    allow_unstable: true,
                 };
                 let mod_path = module.find_path(sema.db, module_def, cfg).ok_or_else(|| {
                     match_error!("Failed to render template path `{}` at match location")
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index bc9843f3f35a2..cfd8919730ad2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -413,8 +413,7 @@ fn rewrite_url_link(db: &RootDatabase, def: Definition, target: &str) -> Option<
 fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> {
     def.canonical_module_path(db).map(|it| {
         let mut path = String::new();
-        it.flat_map(|it| it.name(db))
-            .for_each(|name| format_to!(path, "{}/", name.unescaped().display(db)));
+        it.flat_map(|it| it.name(db)).for_each(|name| format_to!(path, "{}/", name.as_str()));
         path
     })
 }
@@ -590,10 +589,10 @@ fn filename_and_frag_for_def(
     let res = match def {
         Definition::Adt(adt) => match adt {
             Adt::Struct(s) => {
-                format!("struct.{}.html", s.name(db).unescaped().display(db.upcast()))
+                format!("struct.{}.html", s.name(db).as_str())
             }
-            Adt::Enum(e) => format!("enum.{}.html", e.name(db).unescaped().display(db.upcast())),
-            Adt::Union(u) => format!("union.{}.html", u.name(db).unescaped().display(db.upcast())),
+            Adt::Enum(e) => format!("enum.{}.html", e.name(db).as_str()),
+            Adt::Union(u) => format!("union.{}.html", u.name(db).as_str()),
         },
         Definition::Crate(_) => String::from("index.html"),
         Definition::Module(m) => match m.name(db) {
@@ -603,48 +602,48 @@ fn filename_and_frag_for_def(
                     Some(kw) => {
                         format!("keyword.{}.html", kw)
                     }
-                    None => format!("{}/index.html", name.unescaped().display(db.upcast())),
+                    None => format!("{}/index.html", name.as_str()),
                 }
             }
             None => String::from("index.html"),
         },
         Definition::Trait(t) => {
-            format!("trait.{}.html", t.name(db).unescaped().display(db.upcast()))
+            format!("trait.{}.html", t.name(db).as_str())
         }
         Definition::TraitAlias(t) => {
-            format!("traitalias.{}.html", t.name(db).unescaped().display(db.upcast()))
+            format!("traitalias.{}.html", t.name(db).as_str())
         }
         Definition::TypeAlias(t) => {
-            format!("type.{}.html", t.name(db).unescaped().display(db.upcast()))
+            format!("type.{}.html", t.name(db).as_str())
         }
         Definition::BuiltinType(t) => {
-            format!("primitive.{}.html", t.name().unescaped().display(db.upcast()))
+            format!("primitive.{}.html", t.name().as_str())
         }
         Definition::Function(f) => {
-            format!("fn.{}.html", f.name(db).unescaped().display(db.upcast()))
+            format!("fn.{}.html", f.name(db).as_str())
         }
         Definition::Variant(ev) => {
             format!(
                 "enum.{}.html#variant.{}",
-                ev.parent_enum(db).name(db).unescaped().display(db.upcast()),
-                ev.name(db).unescaped().display(db.upcast())
+                ev.parent_enum(db).name(db).as_str(),
+                ev.name(db).as_str()
             )
         }
         Definition::Const(c) => {
-            format!("const.{}.html", c.name(db)?.unescaped().display(db.upcast()))
+            format!("const.{}.html", c.name(db)?.as_str())
         }
         Definition::Static(s) => {
-            format!("static.{}.html", s.name(db).unescaped().display(db.upcast()))
+            format!("static.{}.html", s.name(db).as_str())
         }
         Definition::Macro(mac) => match mac.kind(db) {
             hir::MacroKind::Declarative
             | hir::MacroKind::BuiltIn
             | hir::MacroKind::Attr
             | hir::MacroKind::ProcMacro => {
-                format!("macro.{}.html", mac.name(db).unescaped().display(db.upcast()))
+                format!("macro.{}.html", mac.name(db).as_str())
             }
             hir::MacroKind::Derive => {
-                format!("derive.{}.html", mac.name(db).unescaped().display(db.upcast()))
+                format!("derive.{}.html", mac.name(db).as_str())
             }
         },
         Definition::Field(field) => {
@@ -654,11 +653,7 @@ fn filename_and_frag_for_def(
                 hir::VariantDef::Variant(it) => Definition::Variant(it),
             };
             let (_, file, _) = filename_and_frag_for_def(db, def)?;
-            return Some((
-                def,
-                file,
-                Some(format!("structfield.{}", field.name(db).unescaped().display(db.upcast()))),
-            ));
+            return Some((def, file, Some(format!("structfield.{}", field.name(db).as_str()))));
         }
         Definition::SelfType(impl_) => {
             let adt = impl_.self_ty(db).as_adt()?.into();
@@ -667,7 +662,7 @@ fn filename_and_frag_for_def(
             return Some((adt, file, Some(String::from("impl"))));
         }
         Definition::ExternCrateDecl(it) => {
-            format!("{}/index.html", it.name(db).unescaped().display(db.upcast()))
+            format!("{}/index.html", it.name(db).as_str())
         }
         Definition::Local(_)
         | Definition::GenericParam(_)
@@ -699,16 +694,16 @@ fn get_assoc_item_fragment(db: &dyn HirDatabase, assoc_item: hir::AssocItem) ->
             // Rustdoc makes this decision based on whether a method 'has defaultness'.
             // Currently this is only the case for provided trait methods.
             if is_trait_method && !function.has_body(db) {
-                format!("tymethod.{}", function.name(db).unescaped().display(db.upcast()))
+                format!("tymethod.{}", function.name(db).as_str())
             } else {
-                format!("method.{}", function.name(db).unescaped().display(db.upcast()))
+                format!("method.{}", function.name(db).as_str())
             }
         }
         AssocItem::Const(constant) => {
-            format!("associatedconstant.{}", constant.name(db)?.unescaped().display(db.upcast()))
+            format!("associatedconstant.{}", constant.name(db)?.as_str())
         }
         AssocItem::TypeAlias(ty) => {
-            format!("associatedtype.{}", ty.name(db).unescaped().display(db.upcast()))
+            format!("associatedtype.{}", ty.name(db).as_str())
         }
     })
 }
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 f804cc3677274..d18732a6b846b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -5,10 +5,14 @@ use crate::{
     navigation_target::{self, ToNav},
     FilePosition, NavigationTarget, RangeInfo, TryToNav, UpmappingResult,
 };
-use hir::{AsAssocItem, AssocItem, FileRange, InFile, MacroFileIdExt, ModuleDef, Semantics};
+use hir::{
+    sym, AsAssocItem, AssocItem, CallableKind, FileRange, HasCrate, InFile, MacroFileIdExt,
+    ModuleDef, Semantics,
+};
 use ide_db::{
     base_db::{AnchoredPath, FileLoader, SourceDatabase},
     defs::{Definition, IdentClass},
+    famous_defs::FamousDefs,
     helpers::pick_best_token,
     RootDatabase, SymbolKind,
 };
@@ -129,15 +133,74 @@ pub(crate) fn goto_definition(
     Some(RangeInfo::new(original_token.text_range(), navs))
 }
 
-// If the token is into(), try_into(), parse(), search the definition of From, TryFrom, FromStr.
+// If the token is into(), try_into(), search the definition of From, TryFrom.
 fn find_definition_for_known_blanket_dual_impls(
     sema: &Semantics<'_, RootDatabase>,
     original_token: &SyntaxToken,
 ) -> Option<Vec<NavigationTarget>> {
     let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?;
-    let target_method = sema.resolve_known_blanket_dual_impls(&method_call)?;
+    let callable = sema.resolve_method_call_as_callable(&method_call)?;
+    let CallableKind::Function(f) = callable.kind() else { return None };
+    let assoc = f.as_assoc_item(sema.db)?;
+
+    let return_type = callable.return_type();
+    let fd = FamousDefs(sema, return_type.krate(sema.db));
+
+    let t = match assoc.container(sema.db) {
+        hir::AssocItemContainer::Trait(t) => t,
+        hir::AssocItemContainer::Impl(impl_)
+            if impl_.self_ty(sema.db).is_str() && f.name(sema.db) == sym::parse =>
+        {
+            let t = fd.core_convert_FromStr()?;
+            let t_f = t.function(sema.db, &sym::from_str)?;
+            return sema
+                .resolve_trait_impl_method(
+                    return_type.clone(),
+                    t,
+                    t_f,
+                    [return_type.type_arguments().next()?],
+                )
+                .map(|f| def_to_nav(sema.db, f.into()));
+        }
+        hir::AssocItemContainer::Impl(_) => return None,
+    };
 
-    let def = Definition::from(target_method);
+    let fn_name = f.name(sema.db);
+    let f = if fn_name == sym::into && fd.core_convert_Into() == Some(t) {
+        let dual = fd.core_convert_From()?;
+        let dual_f = dual.function(sema.db, &sym::from)?;
+        sema.resolve_trait_impl_method(
+            return_type.clone(),
+            dual,
+            dual_f,
+            [return_type, callable.receiver_param(sema.db)?.1],
+        )?
+    } else if fn_name == sym::try_into && fd.core_convert_TryInto() == Some(t) {
+        let dual = fd.core_convert_TryFrom()?;
+        let dual_f = dual.function(sema.db, &sym::try_from)?;
+        sema.resolve_trait_impl_method(
+            return_type.clone(),
+            dual,
+            dual_f,
+            // Extract the `T` from `Result<T, ..>`
+            [return_type.type_arguments().next()?, callable.receiver_param(sema.db)?.1],
+        )?
+    } else if fn_name == sym::to_string && fd.alloc_string_ToString() == Some(t) {
+        let dual = fd.core_fmt_Display()?;
+        let dual_f = dual.function(sema.db, &sym::fmt)?;
+        sema.resolve_trait_impl_method(
+            return_type.clone(),
+            dual,
+            dual_f,
+            [callable.receiver_param(sema.db)?.1.strip_reference()],
+        )?
+    } else {
+        return None;
+    };
+    // Assert that we got a trait impl function, if we are back in a trait definition we didn't
+    // succeed
+    let _t = f.as_assoc_item(sema.db)?.implemented_trait(sema.db)?;
+    let def = Definition::from(f);
     Some(def_to_nav(sema.db, def))
 }
 
@@ -3168,18 +3231,45 @@ fn f() {
             r#"
 //- minicore: from, str
 struct A;
-
 impl FromStr for A {
     type Error = String;
-
     fn from_str(value: &str) -> Result<Self, Self::Error> {
      //^^^^^^^^
         Ok(A)
     }
 }
-
 fn f() {
     let a: Result<A, _> = "aaaaaa".parse$0();
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn to_string_call_to_display_definition() {
+        check(
+            r#"
+//- minicore:fmt
+//- /alloc.rs crate:alloc
+pub mod string {
+    pub struct String;
+    pub trait ToString {
+        fn to_string(&self) -> String;
+    }
+
+    impl<T: core::fmt::Display> ToString for T {
+        fn to_string(&self) -> String { String }
+    }
+}
+//- /lib.rs crate:lib deps:alloc
+use alloc::string::ToString;
+struct A;
+impl core::fmt::Display for A {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {}
+    // ^^^
+}
+fn f() {
+    A.to_string$0();
 }
         "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 18a3fed07ece1..9d4c103fc2e01 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -346,7 +346,7 @@ fn hover_offset(
         .unique()
         .reduce(|mut acc: HoverResult, HoverResult { markup, actions }| {
             acc.actions.extend(actions);
-            acc.markup = Markup::from(format!("{}\n---\n{markup}", acc.markup));
+            acc.markup = Markup::from(format!("{}\n\n---\n{markup}", acc.markup));
             acc
         })
         .map(|mut res: HoverResult| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index 46242b75dd0b9..40f3406b72d37 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -1082,7 +1082,19 @@ fn render_memory_layout(
 
     if config.niches {
         if let Some(niches) = layout.niches() {
-            format_to!(label, "niches = {niches}, ");
+            if niches > 1024 {
+                if niches.is_power_of_two() {
+                    format_to!(label, "niches = 2{}, ", pwr2_to_exponent(niches));
+                } else if is_pwr2plus1(niches) {
+                    format_to!(label, "niches = 2{} + 1, ", pwr2_to_exponent(niches - 1));
+                } else if is_pwr2minus1(niches) {
+                    format_to!(label, "niches = 2{} - 1, ", pwr2_to_exponent(niches + 1));
+                } else {
+                    format_to!(label, "niches = a lot, ");
+                }
+            } else {
+                format_to!(label, "niches = {niches}, ");
+            }
         }
     }
     label.pop(); // ' '
@@ -1210,3 +1222,74 @@ fn render_dyn_compatibility(
         }
     }
 }
+
+fn is_pwr2minus1(val: u128) -> bool {
+    val == u128::MAX || (val + 1).is_power_of_two()
+}
+
+fn is_pwr2plus1(val: u128) -> bool {
+    val != 0 && (val - 1).is_power_of_two()
+}
+
+/// Formats a power of two as an exponent of two, i.e. 16 => ⁴. Note that `num` MUST be a power
+/// of 2, or this function will panic.
+fn pwr2_to_exponent(num: u128) -> String {
+    const DIGITS: [char; 10] = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'];
+    assert_eq!(num.count_ones(), 1);
+    num.trailing_zeros()
+        .to_string()
+        .chars()
+        .map(|c| c.to_digit(10).unwrap() as usize)
+        .map(|idx| DIGITS[idx])
+        .collect::<String>()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    const TESTERS: [u128; 10] = [0, 1, 2, 3, 4, 255, 256, 257, u128::MAX - 1, u128::MAX];
+
+    #[test]
+    fn test_is_pwr2minus1() {
+        const OUTCOMES: [bool; 10] =
+            [true, true, false, true, false, true, false, false, false, true];
+        for (test, expected) in TESTERS.iter().zip(OUTCOMES) {
+            let actual = is_pwr2minus1(*test);
+            assert_eq!(actual, expected, "is_pwr2minu1({test}) gave {actual}, expected {expected}");
+        }
+    }
+
+    #[test]
+    fn test_is_pwr2plus1() {
+        const OUTCOMES: [bool; 10] =
+            [false, false, true, true, false, false, false, true, false, false];
+        for (test, expected) in TESTERS.iter().zip(OUTCOMES) {
+            let actual = is_pwr2plus1(*test);
+            assert_eq!(actual, expected, "is_pwr2plus1({test}) gave {actual}, expected {expected}");
+        }
+    }
+
+    #[test]
+    fn test_pwr2_to_exponent() {
+        const TESTERS: [u128; 9] = [
+            1,
+            2,
+            4,
+            8,
+            16,
+            9223372036854775808,
+            18446744073709551616,
+            36893488147419103232,
+            170141183460469231731687303715884105728,
+        ];
+        const OUTCOMES: [&str; 9] = ["⁰", "¹", "²", "³", "⁴", "⁶³", "⁶⁴", "⁶⁵", "¹²⁷"];
+        for (test, expected) in TESTERS.iter().zip(OUTCOMES) {
+            let actual = pwr2_to_exponent(*test);
+            assert_eq!(
+                actual, expected,
+                "pwr2_to_exponent({test}) returned {actual}, expected {expected}",
+            );
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 014b751f95b0c..8c32cc9720af4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -303,6 +303,7 @@ m!(ab$0c);
             ---
 
             Outer
+
             ---
 
             ```rust
@@ -1357,7 +1358,7 @@ fn hover_enum_limit() {
 
             ---
 
-            size = 12 (0xC), align = 4, niches = 4294967288
+            size = 12 (0xC), align = 4, niches = a lot
         "#]],
     );
 }
@@ -4401,6 +4402,7 @@ fn main() {
             ---
 
             size = 8, align = 8, niches = 1
+
             ---
 
             ```rust
@@ -10094,6 +10096,7 @@ fn bar() {
             ```rust
             let field: i32
             ```
+
             ---
 
             ```rust
@@ -10128,6 +10131,7 @@ fn bar() {
             ---
 
             size = 4, align = 4
+
             ---
 
             ```rust
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 6d83a747d7669..1f723c85df7aa 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -209,7 +209,7 @@ fn hints(
 ) {
     closing_brace::hints(hints, sema, config, file_id, node.clone());
     if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
-        generic_param::hints(hints, sema, config, any_has_generic_args);
+        generic_param::hints(hints, famous_defs, config, any_has_generic_args);
     }
 
     match_ast! {
@@ -300,22 +300,23 @@ pub struct InlayHintsConfig {
     pub closing_brace_hints_min_lines: Option<usize>,
     pub fields_to_resolve: InlayFieldsToResolve,
 }
+
 impl InlayHintsConfig {
-    fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> Lazy<TextEdit> {
+    fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> LazyProperty<TextEdit> {
         if self.fields_to_resolve.resolve_text_edits {
-            Lazy::Lazy
+            LazyProperty::Lazy
         } else {
             let edit = finish();
             never!(edit.is_empty(), "inlay hint produced an empty text edit");
-            Lazy::Computed(edit)
+            LazyProperty::Computed(edit)
         }
     }
 
-    fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> Lazy<InlayTooltip> {
+    fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> LazyProperty<InlayTooltip> {
         if self.fields_to_resolve.resolve_hint_tooltip
             && self.fields_to_resolve.resolve_label_tooltip
         {
-            Lazy::Lazy
+            LazyProperty::Lazy
         } else {
             let tooltip = finish();
             never!(
@@ -326,7 +327,20 @@ impl InlayHintsConfig {
                 .is_empty(),
                 "inlay hint produced an empty tooltip"
             );
-            Lazy::Computed(tooltip)
+            LazyProperty::Computed(tooltip)
+        }
+    }
+
+    /// This always reports a resolvable location, so only use this when it is very likely for a
+    /// location link to actually resolve but where computing `finish` would be costly.
+    fn lazy_location_opt(
+        &self,
+        finish: impl FnOnce() -> Option<FileRange>,
+    ) -> Option<LazyProperty<FileRange>> {
+        if self.fields_to_resolve.resolve_label_location {
+            Some(LazyProperty::Lazy)
+        } else {
+            finish().map(LazyProperty::Computed)
         }
     }
 }
@@ -441,7 +455,7 @@ pub struct InlayHint {
     /// The actual label to show in the inlay hint.
     pub label: InlayHintLabel,
     /// Text edit to apply when "accepting" this inlay hint.
-    pub text_edit: Option<Lazy<TextEdit>>,
+    pub text_edit: Option<LazyProperty<TextEdit>>,
     /// Range to recompute inlay hints when trying to resolve for this hint. If this is none, the
     /// hint does not support resolving.
     pub resolve_parent: Option<TextRange>,
@@ -449,15 +463,15 @@ pub struct InlayHint {
 
 /// A type signaling that a value is either computed, or is available for computation.
 #[derive(Clone, Debug)]
-pub enum Lazy<T> {
+pub enum LazyProperty<T> {
     Computed(T),
     Lazy,
 }
 
-impl<T> Lazy<T> {
+impl<T> LazyProperty<T> {
     pub fn computed(self) -> Option<T> {
         match self {
-            Lazy::Computed(it) => Some(it),
+            LazyProperty::Computed(it) => Some(it),
             _ => None,
         }
     }
@@ -508,8 +522,8 @@ pub struct InlayHintLabel {
 impl InlayHintLabel {
     pub fn simple(
         s: impl Into<String>,
-        tooltip: Option<Lazy<InlayTooltip>>,
-        linked_location: Option<FileRange>,
+        tooltip: Option<LazyProperty<InlayTooltip>>,
+        linked_location: Option<LazyProperty<FileRange>>,
     ) -> InlayHintLabel {
         InlayHintLabel {
             parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
@@ -593,16 +607,16 @@ pub struct InlayHintLabelPart {
     /// refers to (not necessarily the location itself).
     /// When setting this, no tooltip must be set on the containing hint, or VS Code will display
     /// them both.
-    pub linked_location: Option<FileRange>,
+    pub linked_location: Option<LazyProperty<FileRange>>,
     /// The tooltip to show when hovering over the inlay hint, this may invoke other actions like
     /// hover requests to show.
-    pub tooltip: Option<Lazy<InlayTooltip>>,
+    pub tooltip: Option<LazyProperty<InlayTooltip>>,
 }
 
 impl std::hash::Hash for InlayHintLabelPart {
     fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
         self.text.hash(state);
-        self.linked_location.hash(state);
+        self.linked_location.is_some().hash(state);
         self.tooltip.is_some().hash(state);
     }
 }
@@ -610,7 +624,9 @@ impl std::hash::Hash for InlayHintLabelPart {
 impl fmt::Debug for InlayHintLabelPart {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Self { text, linked_location: None, tooltip: None | Some(Lazy::Lazy) } => text.fmt(f),
+            Self { text, linked_location: None, tooltip: None | Some(LazyProperty::Lazy) } => {
+                text.fmt(f)
+            }
             Self { text, linked_location, tooltip } => f
                 .debug_struct("InlayHintLabelPart")
                 .field("text", text)
@@ -618,8 +634,10 @@ impl fmt::Debug for InlayHintLabelPart {
                 .field(
                     "tooltip",
                     &tooltip.as_ref().map_or("", |it| match it {
-                        Lazy::Computed(InlayTooltip::String(it) | InlayTooltip::Markdown(it)) => it,
-                        Lazy::Lazy => "",
+                        LazyProperty::Computed(
+                            InlayTooltip::String(it) | InlayTooltip::Markdown(it),
+                        ) => it,
+                        LazyProperty::Lazy => "",
                     }),
                 )
                 .finish(),
@@ -632,7 +650,8 @@ struct InlayHintLabelBuilder<'a> {
     db: &'a RootDatabase,
     result: InlayHintLabel,
     last_part: String,
-    location: Option<FileRange>,
+    resolve: bool,
+    location: Option<LazyProperty<FileRange>>,
 }
 
 impl fmt::Write for InlayHintLabelBuilder<'_> {
@@ -645,11 +664,16 @@ impl HirWrite for InlayHintLabelBuilder<'_> {
     fn start_location_link(&mut self, def: ModuleDefId) {
         never!(self.location.is_some(), "location link is already started");
         self.make_new_part();
-        let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return };
-        let location = location.call_site();
-        let location =
-            FileRange { file_id: location.file_id, range: location.focus_or_full_range() };
-        self.location = Some(location);
+
+        self.location = Some(if self.resolve {
+            LazyProperty::Lazy
+        } else {
+            LazyProperty::Computed({
+                let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return };
+                let location = location.call_site();
+                FileRange { file_id: location.file_id, range: location.focus_or_full_range() }
+            })
+        });
     }
 
     fn end_location_link(&mut self) {
@@ -735,6 +759,7 @@ fn label_of_ty(
         last_part: String::new(),
         location: None,
         result: InlayHintLabel::default(),
+        resolve: config.fields_to_resolve.resolve_label_location,
     };
     let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config, edition);
     let r = label_builder.finish();
@@ -783,7 +808,7 @@ fn ty_to_text_edit(
     ty: &hir::Type,
     offset_to_insert: TextSize,
     prefix: impl Into<String>,
-) -> Option<Lazy<TextEdit>> {
+) -> Option<LazyProperty<TextEdit>> {
     // FIXME: Limit the length and bail out on excess somehow?
     let rendered = sema
         .scope(node_for_hint)
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
index ab5464156f0a7..01a1a4545c478 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
@@ -1203,6 +1203,40 @@ fn f5<G: T<Assoc = ()>>(it: G) {
     let l = it.f();
       //^ ()
 }
+"#,
+        );
+    }
+
+    #[test]
+    fn regression_19007() {
+        check_types(
+            r#"
+trait Foo {
+    type Assoc;
+
+    fn foo(&self) -> Self::Assoc;
+}
+
+trait Bar {
+    type Target;
+}
+
+trait Baz<T> {}
+
+struct Struct<T: Foo> {
+    field: T,
+}
+
+impl<T> Struct<T>
+where
+    T: Foo,
+    T::Assoc: Baz<<T::Assoc as Bar>::Target> + Bar,
+{
+    fn f(&self) {
+        let x = self.field.foo();
+          //^ impl Baz<<<T as Foo>::Assoc as Bar>::Target> + Bar
+    }
+}
 "#,
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs
index 429ddd31cbd0a..e9b728bcaa75d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs
@@ -22,11 +22,7 @@ pub(super) fn hints(
         return None;
     }
 
-    let linked_location =
-        famous_defs.core_marker_Sized().and_then(|it| it.try_to_nav(sema.db)).map(|it| {
-            let n = it.call_site();
-            FileRange { file_id: n.file_id, range: n.focus_or_full_range() }
-        });
+    let sized_trait = famous_defs.core_marker_Sized();
 
     for param in params.type_or_const_params() {
         match param {
@@ -48,7 +44,17 @@ pub(super) fn hints(
                         }
                         hint.parts.push(InlayHintLabelPart {
                             text: "Sized".to_owned(),
-                            linked_location,
+                            linked_location: sized_trait.and_then(|it| {
+                                config.lazy_location_opt(|| {
+                                    it.try_to_nav(sema.db).map(|it| {
+                                        let n = it.call_site();
+                                        FileRange {
+                                            file_id: n.file_id,
+                                            range: n.focus_or_full_range(),
+                                        }
+                                    })
+                                })
+                            }),
                             tooltip: None,
                         });
                         if has_bounds {
@@ -134,12 +140,14 @@ fn foo<T>() {}
                             InlayHintLabelPart {
                                 text: "Sized",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            1,
-                                        ),
-                                        range: 135..140,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                1,
+                                            ),
+                                            range: 135..140,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
index 7fa7ab1a94d63..8471547727fed 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
@@ -81,7 +81,10 @@ mod tests {
 
     use crate::{
         fixture,
-        inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
+        inlay_hints::{
+            tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
+            LazyProperty,
+        },
         InlayHintsConfig,
     };
 
@@ -99,7 +102,7 @@ mod tests {
         let (analysis, file_id) = fixture::file(ra_fixture);
         let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap();
         inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| {
-            if let Some(loc) = &mut hint.linked_location {
+            if let Some(LazyProperty::Computed(loc)) = &mut hint.linked_location {
                 loc.range = TextRange::empty(TextSize::from(0));
             }
         });
@@ -134,12 +137,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 63..64,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 63..64,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -151,12 +156,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "A",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 7..8,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 7..8,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -213,12 +220,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "C",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 51..52,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 51..52,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -230,12 +239,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 29..30,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 29..30,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -276,12 +287,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "C",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 51..52,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 51..52,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -293,12 +306,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 29..30,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 29..30,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -340,12 +355,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 23..24,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 23..24,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -353,12 +370,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "X",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 55..56,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 55..56,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -371,12 +390,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "A",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 7..8,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 7..8,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -384,12 +405,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "X",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 55..56,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 55..56,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -435,12 +458,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            1,
-                                        ),
-                                        range: 0..0,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                1,
+                                            ),
+                                            range: 0..0,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -448,12 +473,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            1,
-                                        ),
-                                        range: 0..0,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                1,
+                                            ),
+                                            range: 0..0,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -467,12 +494,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            1,
-                                        ),
-                                        range: 0..0,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                1,
+                                            ),
+                                            range: 0..0,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -480,12 +509,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            1,
-                                        ),
-                                        range: 0..0,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                1,
+                                            ),
+                                            range: 0..0,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -499,12 +530,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            1,
-                                        ),
-                                        range: 0..0,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                1,
+                                            ),
+                                            range: 0..0,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -512,12 +545,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            1,
-                                        ),
-                                        range: 0..0,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                1,
+                                            ),
+                                            range: 0..0,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -531,12 +566,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "MyIter",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 0..0,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 0..0,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -577,12 +614,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 7..13,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 7..13,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -594,12 +633,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 7..13,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 7..13,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -611,12 +652,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 7..13,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 7..13,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
@@ -628,12 +671,14 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "self",
                                 linked_location: Some(
-                                    FileRangeWrapper {
-                                        file_id: FileId(
-                                            0,
-                                        ),
-                                        range: 42..46,
-                                    },
+                                    Computed(
+                                        FileRangeWrapper {
+                                            file_id: FileId(
+                                                0,
+                                            ),
+                                            range: 42..46,
+                                        },
+                                    ),
                                 ),
                                 tooltip: "",
                             },
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
index 90b8be64a46d2..3767d34e2c7a9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
@@ -11,7 +11,10 @@ use syntax::{
     match_ast, SyntaxKind, SyntaxNode, T,
 };
 
-use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind};
+use crate::{
+    inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig,
+    InlayKind,
+};
 
 pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
@@ -141,7 +144,7 @@ pub(super) fn hints(
     acc.push(InlayHint {
         range: closing_token.text_range(),
         kind: InlayKind::ClosingBrace,
-        label: InlayHintLabel::simple(label, None, linked_location),
+        label: InlayHintLabel::simple(label, None, linked_location.map(LazyProperty::Computed)),
         text_edit: None,
         position: InlayHintPosition::After,
         pad_left: true,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
index 906f2acf0c445..3e91618d08e6f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
@@ -53,10 +53,6 @@ pub(super) fn hints(
     let last = captures.len() - 1;
     for (idx, capture) in captures.into_iter().enumerate() {
         let local = capture.local();
-        let source = local.primary_source(sema.db);
-
-        // force cache the source file, otherwise sema lookup will potentially panic
-        _ = sema.parse_or_expand(source.file());
 
         let label = format!(
             "{}{}",
@@ -73,8 +69,17 @@ pub(super) fn hints(
         }
         hint.label.append_part(InlayHintLabelPart {
             text: label,
-            linked_location: source.name().and_then(|name| {
-                name.syntax().original_file_range_opt(sema.db).map(TupleExt::head).map(Into::into)
+            linked_location: config.lazy_location_opt(|| {
+                let source = local.primary_source(sema.db);
+
+                // force cache the source file, otherwise sema lookup will potentially panic
+                _ = sema.parse_or_expand(source.file());
+                source.name().and_then(|name| {
+                    name.syntax()
+                        .original_file_range_opt(sema.db)
+                        .map(TupleExt::head)
+                        .map(Into::into)
+                })
             }),
             tooltip: None,
         });
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs
index 037b328d971fc..762a4c2655181 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs
@@ -1,17 +1,19 @@
 //! Implementation of inlay hints for generic parameters.
-use ide_db::{active_parameter::generic_def_for_node, RootDatabase};
+use ide_db::{active_parameter::generic_def_for_node, famous_defs::FamousDefs};
 use syntax::{
     ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName},
     AstNode,
 };
 
-use crate::{inlay_hints::GenericParameterHints, InlayHint, InlayHintsConfig, InlayKind};
+use crate::{
+    inlay_hints::GenericParameterHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
+};
 
-use super::param_name::{is_argument_similar_to_param_name, render_label};
+use super::param_name::is_argument_similar_to_param_name;
 
 pub(crate) fn hints(
     acc: &mut Vec<InlayHint>,
-    sema: &hir::Semantics<'_, RootDatabase>,
+    FamousDefs(sema, krate): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     node: AnyHasGenericArgs,
 ) -> Option<()> {
@@ -45,12 +47,23 @@ pub(crate) fn hints(
             return None;
         }
 
-        let name = param.name(sema.db);
-        let param_name = name.as_str();
+        let allowed = match (param, &arg) {
+            (hir::GenericParam::TypeParam(_), ast::GenericArg::TypeArg(_)) => type_hints,
+            (hir::GenericParam::ConstParam(_), ast::GenericArg::ConstArg(_)) => const_hints,
+            (hir::GenericParam::LifetimeParam(_), ast::GenericArg::LifetimeArg(_)) => {
+                lifetime_hints
+            }
+            _ => false,
+        };
+        if !allowed {
+            return None;
+        }
+
+        let param_name = param.name(sema.db);
 
         let should_hide = {
             let argument = get_string_representation(&arg)?;
-            is_argument_similar_to_param_name(&argument, param_name)
+            is_argument_similar_to_param_name(&argument, param_name.as_str())
         };
 
         if should_hide {
@@ -59,30 +72,28 @@ pub(crate) fn hints(
 
         let range = sema.original_range_opt(arg.syntax())?.range;
 
-        let source_syntax = match param {
-            hir::GenericParam::TypeParam(it) => {
-                if !type_hints || !matches!(arg, ast::GenericArg::TypeArg(_)) {
-                    return None;
-                }
-                sema.source(it.merge())?.value.syntax().clone()
-            }
-            hir::GenericParam::ConstParam(it) => {
-                if !const_hints || !matches!(arg, ast::GenericArg::ConstArg(_)) {
-                    return None;
-                }
-                let syntax = sema.source(it.merge())?.value.syntax().clone();
-                let const_param = ast::ConstParam::cast(syntax)?;
-                const_param.name()?.syntax().clone()
-            }
-            hir::GenericParam::LifetimeParam(it) => {
-                if !lifetime_hints || !matches!(arg, ast::GenericArg::LifetimeArg(_)) {
-                    return None;
-                }
-                sema.source(it)?.value.syntax().clone()
-            }
-        };
-        let linked_location = sema.original_range_opt(&source_syntax);
-        let label = render_label(param_name, config, linked_location);
+        let colon = if config.render_colons { ":" } else { "" };
+        let label = InlayHintLabel::simple(
+            format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
+            None,
+            config.lazy_location_opt(|| {
+                let source_syntax = match param {
+                    hir::GenericParam::TypeParam(it) => {
+                        sema.source(it.merge()).map(|it| it.value.syntax().clone())
+                    }
+                    hir::GenericParam::ConstParam(it) => {
+                        let syntax = sema.source(it.merge())?.value.syntax().clone();
+                        let const_param = ast::ConstParam::cast(syntax)?;
+                        const_param.name().map(|it| it.syntax().clone())
+                    }
+                    hir::GenericParam::LifetimeParam(it) => {
+                        sema.source(it).map(|it| it.value.syntax().clone())
+                    }
+                };
+                let linked_location = source_syntax.and_then(|it| sema.original_range_opt(&it));
+                linked_location.map(Into::into)
+            }),
+        );
 
         Some(InlayHint {
             range,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
index 1358d3722f897..27c7c3d498187 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -49,7 +49,7 @@ pub(super) fn hints(
             if mir.locals[place.local].ty.adt_id(ChalkTyInterner).is_none() {
                 continue; // Arguably only ADTs have significant drop impls
             }
-            let Some(binding) = local_to_binding.get(place.local) else {
+            let Some(&binding_idx) = local_to_binding.get(place.local) else {
                 continue; // Ignore temporary values
             };
             let range = match terminator.span {
@@ -91,25 +91,26 @@ pub(super) fn hints(
                 },
                 MirSpan::Unknown => continue,
             };
-            let binding_source = source_map
-                .patterns_for_binding(*binding)
-                .first()
-                .and_then(|d| source_map.pat_syntax(*d).ok())
-                .and_then(|d| {
-                    Some(FileRange {
-                        file_id: d.file_id.file_id()?.into(),
-                        range: d.value.text_range(),
-                    })
-                });
-            let binding = &hir.bindings[*binding];
+            let binding = &hir.bindings[binding_idx];
             let name = binding.name.display_no_db(file_id.edition()).to_smolstr();
             if name.starts_with("<ra@") {
                 continue; // Ignore desugared variables
             }
             let mut label = InlayHintLabel::simple(
                 name,
-                Some(config.lazy_tooltip(|| crate::InlayTooltip::String("moz".into()))),
-                binding_source,
+                None,
+                config.lazy_location_opt(|| {
+                    source_map
+                        .patterns_for_binding(binding_idx)
+                        .first()
+                        .and_then(|d| source_map.pat_syntax(*d).ok())
+                        .and_then(|d| {
+                            Some(FileRange {
+                                file_id: d.file_id.file_id()?.into(),
+                                range: d.value.text_range(),
+                            })
+                        })
+                }),
             );
             label.prepend_str("drop(");
             label.append_str(")");
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
index a7b066700c54e..8f01b1bd38b50 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
@@ -3,7 +3,6 @@
 //! fn max(x: i32, y: i32) -> i32 { x + y }
 //! _ = max(/*x*/4, /*y*/4);
 //! ```
-use std::fmt::Display;
 
 use either::Either;
 use hir::{Callable, Semantics};
@@ -20,7 +19,7 @@ use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, Inla
 
 pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
-    FamousDefs(sema, _): &FamousDefs<'_, '_>,
+    FamousDefs(sema, krate): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     _file_id: EditionedFileId,
     expr: ast::Expr,
@@ -37,23 +36,29 @@ pub(super) fn hints(
         .filter_map(|(p, arg)| {
             // Only annotate hints for expressions that exist in the original file
             let range = sema.original_range_opt(arg.syntax())?;
-            let source = sema.source(p)?;
-            let (param_name, name_syntax) = match source.value.as_ref() {
-                Either::Left(pat) => (pat.name()?, pat.name()),
-                Either::Right(param) => match param.pat()? {
-                    ast::Pat::IdentPat(it) => (it.name()?, it.name()),
-                    _ => return None,
-                },
-            };
-            Some((name_syntax, param_name, arg, range))
+            let param_name = p.name(sema.db)?;
+            Some((p, param_name, arg, range))
         })
         .filter(|(_, param_name, arg, _)| {
-            !should_hide_param_name_hint(sema, &callable, &param_name.text(), arg)
+            !should_hide_param_name_hint(sema, &callable, param_name.as_str(), arg)
         })
         .map(|(param, param_name, _, hir::FileRange { range, .. })| {
-            let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
-
-            let label = render_label(&param_name, config, linked_location);
+            let colon = if config.render_colons { ":" } else { "" };
+            let label = InlayHintLabel::simple(
+                format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
+                None,
+                config.lazy_location_opt(|| {
+                    let source = sema.source(param)?;
+                    let name_syntax = match source.value.as_ref() {
+                        Either::Left(pat) => pat.name(),
+                        Either::Right(param) => match param.pat()? {
+                            ast::Pat::IdentPat(it) => it.name(),
+                            _ => None,
+                        },
+                    }?;
+                    sema.original_range_opt(name_syntax.syntax()).map(Into::into)
+                }),
+            );
             InlayHint {
                 range,
                 kind: InlayKind::Parameter,
@@ -70,16 +75,6 @@ pub(super) fn hints(
     Some(())
 }
 
-pub(super) fn render_label(
-    param_name: impl Display,
-    config: &InlayHintsConfig,
-    linked_location: Option<hir::FileRange>,
-) -> InlayHintLabel {
-    let colon = if config.render_colons { ":" } else { "" };
-
-    InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location.map(Into::into))
-}
-
 fn get_callable(
     sema: &Semantics<'_, RootDatabase>,
     expr: &ast::Expr,
@@ -124,9 +119,7 @@ fn should_hide_param_name_hint(
     }
 
     let fn_name = match callable.kind() {
-        hir::CallableKind::Function(it) => {
-            Some(it.name(sema.db).unescaped().display_no_db().to_smolstr())
-        }
+        hir::CallableKind::Function(it) => Some(it.name(sema.db).as_str().to_smolstr()),
         _ => None,
     };
     let fn_name = fn_name.as_deref();
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 346e2862b0fdd..e942f5a6aac78 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -91,7 +91,8 @@ pub use crate::{
     inlay_hints::{
         AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
         GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart,
-        InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
+        InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LazyProperty,
+        LifetimeElisionHints,
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
@@ -671,7 +672,7 @@ impl Analysis {
         &self,
         config: &CompletionConfig<'_>,
         position: FilePosition,
-        imports: impl IntoIterator<Item = (String, String)> + std::panic::UnwindSafe,
+        imports: impl IntoIterator<Item = String> + std::panic::UnwindSafe,
     ) -> Cancellable<Vec<TextEdit>> {
         Ok(self
             .with_db(|db| ide_completion::resolve_completion_edits(db, config, position, imports))?
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index ba739df3092b3..07dfd83c4eb7f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -263,7 +263,7 @@ fn find_definitions(
                         .and_then(|def| {
                             // if the name differs from the definitions name it has to be an alias
                             if def
-                                .name(sema.db).is_some_and(|it| !it.eq_ident(name_ref.text().as_str()))
+                                .name(sema.db).is_some_and(|it| it.as_str() != name_ref.text().trim_start_matches("r#"))
                             {
                                 Err(format_err!("Renaming aliases is currently unsupported"))
                             } else {
diff --git a/src/tools/rust-analyzer/crates/intern/Cargo.toml b/src/tools/rust-analyzer/crates/intern/Cargo.toml
index 5e7ee54c6af77..c0358ef929b4d 100644
--- a/src/tools/rust-analyzer/crates/intern/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/intern/Cargo.toml
@@ -19,7 +19,6 @@ dashmap.workspace = true
 hashbrown.workspace = true
 rustc-hash.workspace = true
 triomphe.workspace = true
-sptr = "0.3.2"
 
 [lints]
 workspace = true
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
index 200b14027f804..b3bf285edfb11 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
@@ -13,7 +13,6 @@ use std::{
 use dashmap::{DashMap, SharedValue};
 use hashbrown::{hash_map::RawEntryMut, HashMap};
 use rustc_hash::FxHasher;
-use sptr::Strict;
 use triomphe::Arc;
 
 pub mod symbols;
@@ -84,7 +83,7 @@ impl TaggedArcPtr {
     #[inline]
     pub(crate) unsafe fn try_as_arc_owned(self) -> Option<ManuallyDrop<Arc<Box<str>>>> {
         // Unpack the tag from the alignment niche
-        let tag = Strict::addr(self.packed.as_ptr()) & Self::BOOL_BITS;
+        let tag = self.packed.as_ptr().addr() & Self::BOOL_BITS;
         if tag != 0 {
             // Safety: We checked that the tag is non-zero -> true, so we are pointing to the data offset of an `Arc`
             Some(ManuallyDrop::new(unsafe {
@@ -99,40 +98,18 @@ impl TaggedArcPtr {
     fn pack_arc(ptr: NonNull<*const str>) -> NonNull<*const str> {
         let packed_tag = true as usize;
 
-        // can't use this strict provenance stuff here due to trait methods not being const
-        // unsafe {
-        //     // Safety: The pointer is derived from a non-null
-        //     NonNull::new_unchecked(Strict::map_addr(ptr.as_ptr(), |addr| {
-        //         // Safety:
-        //         // - The pointer is `NonNull` => it's address is `NonZero<usize>`
-        //         // - `P::BITS` least significant bits are always zero (`Pointer` contract)
-        //         // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
-        //         //
-        //         // Thus `addr >> T::BITS` is guaranteed to be non-zero.
-        //         //
-        //         // `{non_zero} | packed_tag` can't make the value zero.
-
-        //         (addr >> Self::BOOL_BITS) | packed_tag
-        //     }))
-        // }
-        // so what follows is roughly what the above looks like but inlined
-
-        let self_addr = ptr.as_ptr() as *const *const str as usize;
-        let addr = self_addr | packed_tag;
-        let dest_addr = addr as isize;
-        let offset = dest_addr.wrapping_sub(self_addr as isize);
-
-        // SAFETY: The resulting pointer is guaranteed to be NonNull as we only modify the niche bytes
-        unsafe { NonNull::new_unchecked(ptr.as_ptr().cast::<u8>().wrapping_offset(offset).cast()) }
+        unsafe {
+            // Safety: The pointer is derived from a non-null and bit-oring it with true (1) will
+            // not make it null.
+            NonNull::new_unchecked(ptr.as_ptr().map_addr(|addr| addr | packed_tag))
+        }
     }
 
     #[inline]
     pub(crate) fn pointer(self) -> NonNull<*const str> {
         // SAFETY: The resulting pointer is guaranteed to be NonNull as we only modify the niche bytes
         unsafe {
-            NonNull::new_unchecked(Strict::map_addr(self.packed.as_ptr(), |addr| {
-                addr & !Self::BOOL_BITS
-            }))
+            NonNull::new_unchecked(self.packed.as_ptr().map_addr(|addr| addr & !Self::BOOL_BITS))
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index b3b46421b50fb..9bc78ff87b8aa 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -240,8 +240,10 @@ define_symbols! {
     format_unsafe_arg,
     format,
     freeze,
+    from,
     From,
     FromStr,
+    from_str,
     from_output,
     from_residual,
     from_usize,
@@ -273,6 +275,8 @@ define_symbols! {
     index_mut,
     index,
     Index,
+    into,
+    Into,
     into_future,
     into_iter,
     IntoFuture,
@@ -361,6 +365,7 @@ define_symbols! {
     panic_nounwind,
     panic,
     Param,
+    parse,
     partial_ord,
     PartialEq,
     PartialOrd,
@@ -389,6 +394,7 @@ define_symbols! {
     RangeToInclusive,
     Ready,
     receiver,
+    receiver_target,
     recursion_limit,
     register_attr,
     register_tool,
@@ -454,13 +460,17 @@ define_symbols! {
     termination,
     test_case,
     test,
+    then,
     thiscall,
+    to_string,
     trace_macros,
     transmute_opts,
     transmute_trait,
     transparent,
+    try_into,
     Try,
     TryFrom,
+    try_from,
     tuple_trait,
     u128,
     u16,
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index 00446b27cf2f3..5654c04a59287 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -256,6 +256,24 @@ impl ProjectFolders {
             fsc.add_file_set(file_set_roots)
         }
 
+        for ws in workspaces.iter() {
+            let mut file_set_roots: Vec<VfsPath> = vec![];
+            let mut entries = vec![];
+
+            for buildfile in ws.buildfiles() {
+                file_set_roots.push(VfsPath::from(buildfile.to_owned()));
+                entries.push(buildfile.to_owned());
+            }
+
+            if !file_set_roots.is_empty() {
+                let entry = vfs::loader::Entry::Files(entries);
+                res.watch.push(res.load.len());
+                res.load.push(entry);
+                local_filesets.push(fsc.len() as u64);
+                fsc.add_file_set(file_set_roots)
+            }
+        }
+
         if let Some(user_config_path) = user_config_dir_path {
             let ratoml_path = {
                 let mut p = user_config_path.to_path_buf();
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index c7614849e015b..59293ee3f9659 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -392,12 +392,12 @@ impl server::Span for RaSpanServer {
 
     fn line(&mut self, _span: Self::Span) -> usize {
         // FIXME requires db to resolve line index, THIS IS NOT INCREMENTAL
-        0
+        1
     }
 
     fn column(&mut self, _span: Self::Span) -> usize {
         // FIXME requires db to resolve line index, THIS IS NOT INCREMENTAL
-        0
+        1
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
index 466eb14b55ea5..409cf3cc78134 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -291,11 +291,11 @@ impl server::Span for TokenIdServer {
     }
 
     fn line(&mut self, _span: Self::Span) -> usize {
-        0
+        1
     }
 
     fn column(&mut self, _span: Self::Span) -> usize {
-        0
+        1
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
index 6a88cf022dfb0..a396396761041 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
@@ -63,7 +63,7 @@ use crate::{ManifestPath, TargetKind};
 pub struct ProjectJson {
     /// e.g. `path/to/sysroot`
     pub(crate) sysroot: Option<AbsPathBuf>,
-    /// e.g. `path/to/sysroot/lib/rustlib/src/rust`
+    /// e.g. `path/to/sysroot/lib/rustlib/src/rust/library`
     pub(crate) sysroot_src: Option<AbsPathBuf>,
     project_root: AbsPathBuf,
     /// The path to the rust-project.json file. May be None if this
diff --git a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs
index 4bf9b59e7d038..e472da0c89b0d 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs
@@ -19,7 +19,7 @@ pub fn get(
     let rustc_cfgs = match rustc_cfgs {
         Ok(cfgs) => cfgs,
         Err(e) => {
-            tracing::error!(?e, "failed to get rustc cfgs");
+            tracing::warn!(?e, "failed to get rustc cfgs");
             return vec![];
         }
     };
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index f98d983ac0608..dcd62753cb2f9 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -524,6 +524,17 @@ impl ProjectWorkspace {
         }
     }
 
+    pub fn buildfiles(&self) -> Vec<AbsPathBuf> {
+        match &self.kind {
+            ProjectWorkspaceKind::Json(project) => project
+                .crates()
+                .filter_map(|(_, krate)| krate.build.as_ref().map(|build| build.build_file.clone()))
+                .map(|build_file| self.workspace_root().join(build_file))
+                .collect(),
+            _ => vec![],
+        }
+    }
+
     pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
         self.sysroot.discover_proc_macro_srv()
     }
@@ -568,27 +579,15 @@ impl ProjectWorkspace {
         match &self.kind {
             ProjectWorkspaceKind::Json(project) => project
                 .crates()
-                .map(|(_, krate)| {
-                    // FIXME: PackageRoots dont allow specifying files, only directories
-                    let build_file = krate
-                        .build
-                        .as_ref()
-                        .map(|build| self.workspace_root().join(&build.build_file))
-                        .as_deref()
-                        .and_then(AbsPath::parent)
-                        .map(ToOwned::to_owned);
-
-                    PackageRoot {
-                        is_local: krate.is_workspace_member,
-                        include: krate
-                            .include
-                            .iter()
-                            .cloned()
-                            .chain(build_file)
-                            .chain(self.extra_includes.iter().cloned())
-                            .collect(),
-                        exclude: krate.exclude.clone(),
-                    }
+                .map(|(_, krate)| PackageRoot {
+                    is_local: krate.is_workspace_member,
+                    include: krate
+                        .include
+                        .iter()
+                        .cloned()
+                        .chain(self.extra_includes.iter().cloned())
+                        .collect(),
+                    exclude: krate.exclude.clone(),
                 })
                 .collect::<FxHashSet<_>>()
                 .into_iter()
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 bcaec52019591..18c27c844964b 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
@@ -465,6 +465,7 @@ impl flags::AnalysisStats {
                                 prefer_no_std: false,
                                 prefer_prelude: true,
                                 prefer_absolute: false,
+                                allow_unstable: true,
                             },
                             Edition::LATEST,
                         )
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 3dc4379258fa1..44325fa1a29e6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -453,6 +453,10 @@ config_data! {
         ///
         /// In `match` arms it completes a comma instead.
         completion_addSemicolonToUnit: bool = true,
+        /// Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.
+        completion_autoAwait_enable: bool        = true,
+        /// Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.
+        completion_autoIter_enable: bool        = true,
         /// Toggles the additional completions that automatically add imports when completed.
         /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
         completion_autoimport_enable: bool       = true,
@@ -1484,6 +1488,8 @@ impl Config {
             enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
                 && self.caps.completion_item_edit_resolve(),
             enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(),
+            enable_auto_iter: *self.completion_autoIter_enable(source_root),
+            enable_auto_await: *self.completion_autoAwait_enable(source_root),
             enable_private_editable: self.completion_privateEditable_enable(source_root).to_owned(),
             full_function_signatures: self
                 .completion_fullFunctionSignatures_enable(source_root)
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
index 22f06d68d80d1..2309f94a7429b 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
@@ -88,6 +88,17 @@ pub(crate) enum FlycheckConfig {
     },
 }
 
+impl FlycheckConfig {
+    pub(crate) fn invocation_strategy_once(&self) -> bool {
+        match self {
+            FlycheckConfig::CargoCommand { .. } => false,
+            FlycheckConfig::CustomCommand { invocation_strategy, .. } => {
+                *invocation_strategy == InvocationStrategy::Once
+            }
+        }
+    }
+}
+
 impl fmt::Display for FlycheckConfig {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index 98efc637c2c81..84ba89d9f31f9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -291,9 +291,15 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
     let file_id = state.vfs.read().0.file_id(&vfs_path);
     if let Some(file_id) = file_id {
         let world = state.snapshot();
+        let invocation_strategy_once = state.config.flycheck(None).invocation_strategy_once();
         let may_flycheck_workspace = state.config.flycheck_workspace(None);
         let mut updated = false;
         let task = move || -> std::result::Result<(), ide::Cancelled> {
+            if invocation_strategy_once {
+                let saved_file = vfs_path.as_path().map(|p| p.to_owned());
+                world.flycheck[0].restart_workspace(saved_file.clone());
+            }
+
             let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| {
                 let tgt_kind = it.target_kind();
                 let (tgt_name, root, package) = match it {
@@ -320,16 +326,15 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                 // the user opted into package checks then
                 let package_check_allowed = target.is_some() || !may_flycheck_workspace;
                 if package_check_allowed {
-                    let workspace =
-                        world.workspaces.iter().enumerate().find(|(_, ws)| match &ws.kind {
-                            project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
-                            | project_model::ProjectWorkspaceKind::DetachedFile {
-                                cargo: Some((cargo, _, _)),
-                                ..
-                            } => *cargo.workspace_root() == root,
-                            _ => false,
-                        });
-                    if let Some((idx, _)) = workspace {
+                    let workspace = world.workspaces.iter().position(|ws| match &ws.kind {
+                        project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
+                        | project_model::ProjectWorkspaceKind::DetachedFile {
+                            cargo: Some((cargo, _, _)),
+                            ..
+                        } => *cargo.workspace_root() == root,
+                        _ => false,
+                    });
+                    if let Some(idx) = workspace {
                         world.flycheck[idx].restart_for_package(package, target);
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 190015d7faad8..39cbf53eaa21d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -1154,10 +1154,7 @@ pub(crate) fn handle_completion_resolve(
             .resolve_completion_edits(
                 &forced_resolve_completions_config,
                 position,
-                resolve_data
-                    .imports
-                    .into_iter()
-                    .map(|import| (import.full_import_path, import.imported_name)),
+                resolve_data.imports.into_iter().map(|import| import.full_import_path),
             )?
             .into_iter()
             .flat_map(|edit| edit.into_iter().map(|indel| to_proto::text_edit(&line_index, indel)))
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
index fcfd06679bf2b..5cdc51a1c1995 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -176,6 +176,8 @@ fn integrated_completion_benchmark() {
             fields_to_resolve: CompletionFieldsToResolve::empty(),
             exclude_flyimport: vec![],
             exclude_traits: &[],
+            enable_auto_await: true,
+            enable_auto_iter: true,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -226,6 +228,8 @@ fn integrated_completion_benchmark() {
             fields_to_resolve: CompletionFieldsToResolve::empty(),
             exclude_flyimport: vec![],
             exclude_traits: &[],
+            enable_auto_await: true,
+            enable_auto_iter: true,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -274,6 +278,8 @@ fn integrated_completion_benchmark() {
             fields_to_resolve: CompletionFieldsToResolve::empty(),
             exclude_flyimport: vec![],
             exclude_traits: &[],
+            enable_auto_await: true,
+            enable_auto_iter: true,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
index 61ec576dd4f90..ccffa7a671e66 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
@@ -142,9 +142,8 @@ fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8;
         hasher.update(prefix);
         hasher.update(u32::from(*text_size).to_le_bytes());
     }
-    for (import_path, import_name) in &item.import_to_add {
+    for import_path in &item.import_to_add {
         hasher.update(import_path);
-        hasher.update(import_name);
     }
     hasher.finalize()
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 134de92feab3a..ca4372aa83f8d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -850,7 +850,6 @@ pub struct InlayHintResolveData {
 #[derive(Debug, Serialize, Deserialize)]
 pub struct CompletionImport {
     pub full_import_path: String,
-    pub imported_name: String,
 }
 
 #[derive(Debug, Deserialize, Default)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index a5516e7f9d4fe..bff53cf98b7b8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -11,8 +11,8 @@ use ide::{
     Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
     CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
     FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
-    InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup,
-    NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
+    InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, LazyProperty,
+    Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
     SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
 };
 use ide_db::{assists, rust_doc::format_docs, FxHasher};
@@ -394,10 +394,7 @@ fn completion_item(
             item.import_to_add
                 .clone()
                 .into_iter()
-                .map(|(import_path, import_name)| lsp_ext::CompletionImport {
-                    full_import_path: import_path,
-                    imported_name: import_name,
-                })
+                .map(|import_path| lsp_ext::CompletionImport { full_import_path: import_path })
                 .collect()
         } else {
             Vec::new()
@@ -549,12 +546,11 @@ pub(crate) fn inlay_hint(
 ) -> Cancellable<lsp_types::InlayHint> {
     let hint_needs_resolve = |hint: &InlayHint| -> Option<TextRange> {
         hint.resolve_parent.filter(|_| {
-            hint.text_edit.is_some()
-                || hint
-                    .label
-                    .parts
-                    .iter()
-                    .any(|part| part.linked_location.is_some() || part.tooltip.is_some())
+            hint.text_edit.as_ref().is_some_and(LazyProperty::is_lazy)
+                || hint.label.parts.iter().any(|part| {
+                    part.linked_location.as_ref().is_some_and(LazyProperty::is_lazy)
+                        || part.tooltip.as_ref().is_some_and(LazyProperty::is_lazy)
+                })
         })
     };
 
@@ -569,22 +565,21 @@ pub(crate) fn inlay_hint(
     });
 
     let mut something_to_resolve = false;
-    let text_edits = if snap
-        .config
-        .visual_studio_code_version()
-        .is_none_or(|version| VersionReq::parse(">=1.86.0").unwrap().matches(version))
-        && resolve_range_and_hash.is_some()
-        && fields_to_resolve.resolve_text_edits
-    {
-        something_to_resolve |= inlay_hint.text_edit.is_some();
-        None
-    } else {
-        inlay_hint
-            .text_edit
-            .take()
-            .and_then(|it| it.computed())
-            .map(|it| text_edit_vec(line_index, it))
-    };
+    let text_edits = inlay_hint
+        .text_edit
+        .take()
+        .and_then(|it| match it {
+            LazyProperty::Computed(it) => Some(it),
+            LazyProperty::Lazy => {
+                something_to_resolve |=
+                    snap.config.visual_studio_code_version().is_none_or(|version| {
+                        VersionReq::parse(">=1.86.0").unwrap().matches(version)
+                    }) && resolve_range_and_hash.is_some()
+                        && fields_to_resolve.resolve_text_edits;
+                None
+            }
+        })
+        .map(|it| text_edit_vec(line_index, it));
     let (label, tooltip) = inlay_hint_label(
         snap,
         fields_to_resolve,
@@ -637,22 +632,23 @@ fn inlay_hint_label(
     let (label, tooltip) = match &*label.parts {
         [InlayHintLabelPart { linked_location: None, .. }] => {
             let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
-            let hint_tooltip = if needs_resolve && fields_to_resolve.resolve_hint_tooltip {
-                *something_to_resolve |= tooltip.is_some();
-                None
-            } else {
-                match tooltip.and_then(|it| it.computed()) {
-                    Some(ide::InlayTooltip::String(s)) => {
-                        Some(lsp_types::InlayHintTooltip::String(s))
-                    }
-                    Some(ide::InlayTooltip::Markdown(s)) => {
-                        Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
-                            kind: lsp_types::MarkupKind::Markdown,
-                            value: s,
-                        }))
-                    }
-                    None => None,
+            let tooltip = tooltip.and_then(|it| match it {
+                LazyProperty::Computed(it) => Some(it),
+                LazyProperty::Lazy => {
+                    *something_to_resolve |=
+                        needs_resolve && fields_to_resolve.resolve_hint_tooltip;
+                    None
                 }
+            });
+            let hint_tooltip = match tooltip {
+                Some(ide::InlayTooltip::String(s)) => Some(lsp_types::InlayHintTooltip::String(s)),
+                Some(ide::InlayTooltip::Markdown(s)) => {
+                    Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
+                        kind: lsp_types::MarkupKind::Markdown,
+                        value: s,
+                    }))
+                }
+                None => None,
             };
             (lsp_types::InlayHintLabel::String(text), hint_tooltip)
         }
@@ -661,31 +657,38 @@ fn inlay_hint_label(
                 .parts
                 .into_iter()
                 .map(|part| {
-                    let tooltip = if needs_resolve && fields_to_resolve.resolve_label_tooltip {
-                        *something_to_resolve |= part.tooltip.is_some();
-                        None
-                    } else {
-                        match part.tooltip.and_then(|it| it.computed()) {
-                            Some(ide::InlayTooltip::String(s)) => {
-                                Some(lsp_types::InlayHintLabelPartTooltip::String(s))
-                            }
-                            Some(ide::InlayTooltip::Markdown(s)) => {
-                                Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
-                                    lsp_types::MarkupContent {
-                                        kind: lsp_types::MarkupKind::Markdown,
-                                        value: s,
-                                    },
-                                ))
-                            }
-                            None => None,
+                    let tooltip = part.tooltip.and_then(|it| match it {
+                        LazyProperty::Computed(it) => Some(it),
+                        LazyProperty::Lazy => {
+                            *something_to_resolve |= fields_to_resolve.resolve_label_tooltip;
+                            None
                         }
+                    });
+                    let tooltip = match tooltip {
+                        Some(ide::InlayTooltip::String(s)) => {
+                            Some(lsp_types::InlayHintLabelPartTooltip::String(s))
+                        }
+                        Some(ide::InlayTooltip::Markdown(s)) => {
+                            Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
+                                lsp_types::MarkupContent {
+                                    kind: lsp_types::MarkupKind::Markdown,
+                                    value: s,
+                                },
+                            ))
+                        }
+                        None => None,
                     };
-                    let location = if needs_resolve && fields_to_resolve.resolve_label_location {
-                        *something_to_resolve |= part.linked_location.is_some();
-                        None
-                    } else {
-                        part.linked_location.map(|range| location(snap, range)).transpose()?
-                    };
+                    let location = part
+                        .linked_location
+                        .and_then(|it| match it {
+                            LazyProperty::Computed(it) => Some(it),
+                            LazyProperty::Lazy => {
+                                *something_to_resolve |= fields_to_resolve.resolve_label_location;
+                                None
+                            }
+                        })
+                        .map(|range| location(snap, range))
+                        .transpose()?;
                     Ok(lsp_types::InlayHintLabelPart {
                         value: part.text,
                         tooltip,
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index dca231604fa13..ff027ac5848b3 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -411,6 +411,11 @@ pub fn path_from_text(text: &str) -> ast::Path {
     ast_from_text(&format!("fn main() {{ let test: {text}; }}"))
 }
 
+// FIXME: should not be pub
+pub fn path_from_text_with_edition(text: &str, edition: Edition) -> ast::Path {
+    ast_from_text_with_edition(&format!("fn main() {{ let test: {text}; }}"), edition)
+}
+
 pub fn use_tree_glob() -> ast::UseTree {
     ast_from_text("use *;")
 }
@@ -1230,7 +1235,12 @@ pub fn token_tree(
 
 #[track_caller]
 fn ast_from_text<N: AstNode>(text: &str) -> N {
-    let parse = SourceFile::parse(text, Edition::CURRENT);
+    ast_from_text_with_edition(text, Edition::CURRENT)
+}
+
+#[track_caller]
+fn ast_from_text_with_edition<N: AstNode>(text: &str, edition: Edition) -> N {
+    let parse = SourceFile::parse(text, edition);
     let node = match parse.tree().syntax().descendants().find_map(N::cast) {
         Some(it) => it,
         None => {
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index fd06736a25248..4ed68d18e8071 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -53,6 +53,7 @@
 //!     pin:
 //!     pointee: copy, send, sync, ord, hash, unpin
 //!     range:
+//!     receiver: deref
 //!     result:
 //!     send: sized
 //!     size_of: sized
@@ -513,10 +514,26 @@ pub mod ops {
             fn deref_mut(&mut self) -> &mut Self::Target;
         }
         // endregion:deref_mut
+
+        // region:receiver
+        #[lang = "receiver"]
+        pub trait Receiver {
+            #[lang = "receiver_target"]
+            type Target: ?Sized;
+        }
+
+        impl<P: ?Sized, T: ?Sized> Receiver for P
+        where
+            P: Deref<Target = T>,
+        {
+            type Target = T;
+        }
+        // endregion:receiver
     }
     pub use self::deref::{
         Deref,
         DerefMut, // :deref_mut
+        Receiver, // :receiver
     };
     // endregion:deref
 
diff --git a/src/tools/rust-analyzer/docs/dev/README.md b/src/tools/rust-analyzer/docs/dev/README.md
index 3ba492e095974..c990212d585d2 100644
--- a/src/tools/rust-analyzer/docs/dev/README.md
+++ b/src/tools/rust-analyzer/docs/dev/README.md
@@ -269,19 +269,13 @@ Note: we tag releases by dates, releasing a patch release on the same day should
 
 ## Permissions
 
-There are three sets of people with extra permissions:
+There are two sets of people with extra permissions:
 
-* rust-analyzer GitHub organization [**admins**](https://github.com/orgs/rust-analyzer/people?query=role:owner) (which include current t-compiler leads).
-  Admins have full access to the org.
-* [**review**](https://github.com/orgs/rust-analyzer/teams/review) team in the organization.
-  Reviewers have `r+` access to all of organization's repositories and publish rights on crates.io.
-  They also have direct commit access, but all changes should via bors queue.
+* The [rust-lang](https://github.com/rust-lang) team [t-rust-analyzer](https://github.com/rust-lang/team/blob/master/teams/rust-analyzer.toml).
+  This team has write access to the repository and merge queue permissions (note the repo itself is managed by infra admins).
   It's ok to self-approve if you think you know what you are doing!
-  bors should automatically sync the permissions.
   Feel free to request a review or assign any PR to a reviewer with the relevant expertise to bring the work to their attention.
   Don't feel pressured to review assigned PRs though.
-  If you don't feel like reviewing for whatever reason, someone else will pick the review up!
-* [**triage**](https://github.com/orgs/rust-analyzer/teams/triage) team in the organization.
-  This team can label and close issues.
-
-Note that at the time being you need to be a member of the org yourself to view the links.
+  If you don't feel like reviewing for whatever reason, someone else will pick the review up (but please speak up if you don't feel like it)!
+* The [rust-lang](https://github.com/rust-lang) team [t-rust-analyzer-contributors]([https://github.com/orgs/rust-analyzer/teams/triage](https://github.com/rust-lang/team/blob/master/teams/rust-analyzer-contributors.toml)).
+  This team has general triaging permissions allowing to label, close and re-open issues.
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index a632fc6f5fb87..c7ee4e402363c 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: 2d8604825c458288
+lsp/ext.rs hash: af70cce5d6905e39
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index bd091db58d3f7..b33de1956b8db 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -274,6 +274,16 @@ Whether to automatically add a semicolon when completing unit-returning function
 
 In `match` arms it completes a comma instead.
 --
+[[rust-analyzer.completion.autoAwait.enable]]rust-analyzer.completion.autoAwait.enable (default: `true`)::
++
+--
+Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.
+--
+[[rust-analyzer.completion.autoIter.enable]]rust-analyzer.completion.autoIter.enable (default: `true`)::
++
+--
+Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.
+--
 [[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
 +
 --
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index ffc820e9b7f76..4a2a6f2e36864 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -716,6 +716,32 @@ interface JsonProject {
     /// dependencies as well as sysroot crate (libstd,
     /// libcore and such).
     crates: Crate[];
+    /// Configuration for CLI commands.
+    ///
+    /// These are used for running and debugging binaries
+    /// and tests without encoding build system-specific
+    /// knowledge into rust-analyzer.
+    ///
+    /// # Example
+    ///
+    /// Below is an example of a test runnable. `{label}` and `{test_id}`
+    /// are explained in `Runnable::args`'s documentation below.
+    ///
+    /// ```json
+    /// {
+    ///     "program": "buck",
+    ///     "args": [
+    ///         "test",
+    ///          "{label}",
+    ///          "--",
+    ///          "{test_id}",
+    ///          "--print-passing-details"
+    ///     ],
+    ///     "cwd": "/home/user/repo-root/",
+    ///     "kind": "testOne"
+    /// }
+    /// ```
+    runnables?: Runnable[];
 }
 
 interface Crate {
@@ -726,7 +752,10 @@ interface Crate {
     /// Path to the root module of the crate.
     root_module: string;
     /// Edition of the crate.
-    edition: "2015" | "2018" | "2021";
+    edition: '2015' | '2018' | '2021' | '2024';
+    /// The version of the crate. Used for calculating
+    /// the correct docs.rs URL.
+    version?: string;
     /// Dependencies
     deps: Dep[];
     /// Should this crate be treated as a member of
@@ -757,9 +786,9 @@ interface Crate {
     /// rust-analyzer assumes that files from one
     /// source can't refer to files in another source.
     source?: {
-        include_dirs: string[],
-        exclude_dirs: string[],
-    },
+        include_dirs: string[];
+        exclude_dirs: string[];
+    };
     /// List of cfg groups this crate inherits.
     ///
     /// All cfg in these groups will be concatenated to
@@ -776,21 +805,68 @@ interface Crate {
     target?: string;
     /// Environment variables, used for
     /// the `env!` macro
-    env: { [key: string]: string; },
+    env: { [key: string]: string; };
 
     /// Whether the crate is a proc-macro crate.
     is_proc_macro: boolean;
     /// For proc-macro crates, path to compiled
     /// proc-macro (.so file).
     proc_macro_dylib_path?: string;
+
+    /// Repository, matching the URL that would be used
+    /// in Cargo.toml.
+    repository?: string;
+
+    /// Build-specific data about this crate.
+    build?: BuildInfo;
 }
 
 interface Dep {
     /// Index of a crate in the `crates` array.
-    crate: number,
+    crate: number;
     /// Name as should appear in the (implicit)
     /// `extern crate name` declaration.
-    name: string,
+    name: string;
+}
+
+interface BuildInfo {
+    /// The name associated with this crate.
+    ///
+    /// This is determined by the build system that produced
+    /// the `rust-project.json` in question. For instance, if buck were used,
+    /// the label might be something like `//ide/rust/rust-analyzer:rust-analyzer`.
+    ///
+    /// Do not attempt to parse the contents of this string; it is a build system-specific
+    /// identifier similar to `Crate::display_name`.
+    label: string;
+    /// Path corresponding to the build system-specific file defining the crate.
+    build_file: string;
+    /// The kind of target.
+    ///
+    /// This information is used to determine what sort
+    /// of runnable codelens to provide, if any.
+    target_kind: 'bin' | 'lib' | 'test';
+}
+
+interface Runnable {
+    /// The program invoked by the runnable.
+    ///
+    /// For example, this might be `cargo`, `buck`, or `bazel`.
+    program: string;
+    /// The arguments passed to `program`.
+    args: string[];
+    /// The current working directory of the runnable.
+    cwd: string;
+    /// Used to decide what code lens to offer.
+    ///
+    /// `testOne`: This runnable will be used when the user clicks the 'Run Test'
+    /// CodeLens above a test.
+    ///
+    /// The args for testOne can contain two template strings:
+    /// `{label}` and `{test_id}`. `{label}` will be replaced
+    /// with the `Build::label` and `{test_id}` will be replaced
+    /// with the test name.
+    kind: 'testOne' | string;
 }
 ----
 
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 8b066377f2b2f..f148041ac3eba 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -1143,6 +1143,26 @@
                     }
                 }
             },
+            {
+                "title": "completion",
+                "properties": {
+                    "rust-analyzer.completion.autoAwait.enable": {
+                        "markdownDescription": "Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.",
+                        "default": true,
+                        "type": "boolean"
+                    }
+                }
+            },
+            {
+                "title": "completion",
+                "properties": {
+                    "rust-analyzer.completion.autoIter.enable": {
+                        "markdownDescription": "Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.",
+                        "default": true,
+                        "type": "boolean"
+                    }
+                }
+            },
             {
                 "title": "completion",
                 "properties": {
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 5550bfa6558a1..96dc4f19b82c6 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -361,7 +361,14 @@ export class Ctx implements RustAnalyzerExtensionApi {
             }
         });
 
-        vscode.workspace.onDidChangeTextDocument(async () => {
+        vscode.workspace.onDidChangeTextDocument(async (e) => {
+            if (
+                vscode.window.activeTextEditor?.document !== e.document ||
+                e.contentChanges.length === 0
+            ) {
+                return;
+            }
+
             if (this.syntaxTreeView?.visible) {
                 await this.syntaxTreeProvider?.refresh();
             }
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
index 074bc43388a92..2749557b91a07 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
@@ -80,9 +80,9 @@ pub struct Request {
 
 #[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct Response {
-    // JSON RPC allows this to be null if it was impossible
-    // to decode the request's id. Ignore this special case
-    // and just die horribly.
+    // JSON-RPC allows this to be null if we can't find or parse the
+    // request id. We fail deserialization in that case, so we just
+    // make this field mandatory.
     pub id: RequestId,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub result: Option<serde_json::Value>,
diff --git a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs
index e1887b93b93a0..e5608411cd60e 100644
--- a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs
+++ b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs
@@ -1,6 +1,4 @@
-//
 //@ compile-flags:-Zprint-mono-items=eager
-//@ compile-flags:-Zinline-in-all-cgus
 //@ compile-flags:-Zinline-mir=no
 
 #![crate_type = "lib"]
diff --git a/tests/codegen-units/item-collection/generic-drop-glue.rs b/tests/codegen-units/item-collection/generic-drop-glue.rs
index 6ecf98a032f52..b3a5aeb5825da 100644
--- a/tests/codegen-units/item-collection/generic-drop-glue.rs
+++ b/tests/codegen-units/item-collection/generic-drop-glue.rs
@@ -1,6 +1,4 @@
-//
 //@ compile-flags:-Zprint-mono-items=eager
-//@ compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
 #![crate_type = "lib"]
diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs
index 9087fc6410ab5..ee0b5dc1dd2cb 100644
--- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs
+++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs
@@ -1,5 +1,4 @@
-//
-//@ compile-flags:-Zprint-mono-items=eager -Zinline-in-all-cgus -Zmir-opt-level=0
+//@ compile-flags:-Zprint-mono-items=eager -Zmir-opt-level=0
 
 #![deny(dead_code)]
 #![crate_type = "lib"]
diff --git a/tests/codegen-units/item-collection/non-generic-drop-glue.rs b/tests/codegen-units/item-collection/non-generic-drop-glue.rs
index c4d7942ba1ed9..c2563aabfe56e 100644
--- a/tests/codegen-units/item-collection/non-generic-drop-glue.rs
+++ b/tests/codegen-units/item-collection/non-generic-drop-glue.rs
@@ -1,6 +1,4 @@
-//
 //@ compile-flags:-Zprint-mono-items=eager
-//@ compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
 #![crate_type = "lib"]
diff --git a/tests/codegen-units/item-collection/transitive-drop-glue.rs b/tests/codegen-units/item-collection/transitive-drop-glue.rs
index 18954fab86f66..fe7a2d2aa0119 100644
--- a/tests/codegen-units/item-collection/transitive-drop-glue.rs
+++ b/tests/codegen-units/item-collection/transitive-drop-glue.rs
@@ -1,6 +1,4 @@
-//
 //@ compile-flags:-Zprint-mono-items=eager
-//@ compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
 #![crate_type = "lib"]
diff --git a/tests/codegen-units/item-collection/tuple-drop-glue.rs b/tests/codegen-units/item-collection/tuple-drop-glue.rs
index 2e70d0151eb7c..eff03ea2d0e9d 100644
--- a/tests/codegen-units/item-collection/tuple-drop-glue.rs
+++ b/tests/codegen-units/item-collection/tuple-drop-glue.rs
@@ -1,6 +1,4 @@
-//
 //@ compile-flags:-Zprint-mono-items=eager
-//@ compile-flags:-Zinline-in-all-cgus
 
 #![deny(dead_code)]
 #![crate_type = "lib"]
diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs
index 23e6003dc19fd..97adf72ce2c9b 100644
--- a/tests/codegen-units/item-collection/unsizing.rs
+++ b/tests/codegen-units/item-collection/unsizing.rs
@@ -1,5 +1,4 @@
 //@ compile-flags:-Zprint-mono-items=eager
-//@ compile-flags:-Zinline-in-all-cgus
 //@ compile-flags:-Zmir-opt-level=0
 
 #![deny(dead_code)]
diff --git a/tests/codegen-units/partitioning/README.md b/tests/codegen-units/partitioning/README.md
new file mode 100644
index 0000000000000..5dd6b1281fd9d
--- /dev/null
+++ b/tests/codegen-units/partitioning/README.md
@@ -0,0 +1,14 @@
+# codegen-units/partitioning tests
+
+This test suite is designed to test that codegen unit partitioning works as intended.
+Note that it does not evaluate whether CGU partitioning is *good*. That is the job of the compiler benchmark suite.
+
+All tests in this suite use the flag `-Zprint-mono-items=lazy`, which makes the compiler print a machine-readable summary of all MonoItems that were collected, which CGUs they were assigned to, and the linkage in each CGU. The output looks like:
+```
+MONO_ITEM <item> @@ <cgu name>[<linkage>] <other cgu name>[<linkage in other cgu>]
+```
+DO NOT add tests to this suite that use `-Zprint-mono-items=eager`. That flag changes the way that MonoItem collection works in rather fundamental ways that are otherwise only used by `-Clink-dead-code`, and thus the MonoItems collected and their linkage under `-Zprint-mono-items=eager` does not correlate very well with normal compilation behavior.
+
+The current CGU partitioning algorithm essentially groups MonoItems by which module they are defined in, then merges small CGUs. There are a lot of inline modules in this test suite because that's the only way to observe the partitioning.
+
+Currently, the test suite is very heavily biased towards incremental builds with -Copt-level=0. This is mostly an accident of history; the entire test suite was added as part of supporting incremental compilation in #32779. But also CGU partitioning is *mostly* valuable because the CGU is the unit of incrementality to the codegen backend (cached queries are the unit of incrementality for the rest of the compiler).
diff --git a/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs
index b6c568ed387a1..d3517df03763e 100644
--- a/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs
+++ b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs
@@ -1,7 +1,6 @@
 // NOTE: We always compile this test with -Copt-level=0 because higher opt-levels
 //       prevent drop-glue from participating in share-generics.
-//@ compile-flags:-Zshare-generics=yes -Copt-level=0
-//@ no-prefer-dynamic
+//@ compile-flags: -Zshare-generics=yes -Copt-level=0
 
 #![crate_type = "rlib"]
 
diff --git a/tests/codegen-units/partitioning/extern-drop-glue.rs b/tests/codegen-units/partitioning/extern-drop-glue.rs
index d3bce7b4223cc..ca78c175dbf34 100644
--- a/tests/codegen-units/partitioning/extern-drop-glue.rs
+++ b/tests/codegen-units/partitioning/extern-drop-glue.rs
@@ -1,15 +1,14 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
-// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Zinline-in-all-cgus -Copt-level=0
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
-#![allow(dead_code)]
 #![crate_type = "rlib"]
 
 //@ aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
 
+// This test checks that drop glue is generated, even for types not defined in this crate, and all
+// drop glue is put in the fallback CGU.
+
 //~ MONO_ITEM fn std::ptr::drop_in_place::<cgu_extern_drop_glue::Struct> - shim(Some(cgu_extern_drop_glue::Struct)) @@ extern_drop_glue-fallback.cgu[External]
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
diff --git a/tests/codegen-units/partitioning/extern-generic.rs b/tests/codegen-units/partitioning/extern-generic.rs
index 602a5240283bc..875ebb3098e56 100644
--- a/tests/codegen-units/partitioning/extern-generic.rs
+++ b/tests/codegen-units/partitioning/extern-generic.rs
@@ -1,51 +1,36 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=eager -Zshare-generics=y
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
-#![allow(dead_code)]
 #![crate_type = "lib"]
 
 //@ aux-build:cgu_generic_function.rs
 extern crate cgu_generic_function;
 
-//~ MONO_ITEM fn user @@ extern_generic[Internal]
-fn user() {
+// This test checks that, in an unoptimized build, a generic function and its callees are only
+// instantiated once in this crate.
+
+//~ MONO_ITEM fn user @@ extern_generic[External]
+pub fn user() {
     let _ = cgu_generic_function::foo("abc");
 }
 
-mod mod1 {
+pub mod mod1 {
     use cgu_generic_function;
 
-    //~ MONO_ITEM fn mod1::user @@ extern_generic-mod1[Internal]
-    fn user() {
+    //~ MONO_ITEM fn mod1::user @@ extern_generic-mod1[External]
+    pub fn user() {
         let _ = cgu_generic_function::foo("abc");
     }
 
-    mod mod1 {
+    pub mod mod1 {
         use cgu_generic_function;
 
-        //~ MONO_ITEM fn mod1::mod1::user @@ extern_generic-mod1-mod1[Internal]
-        fn user() {
+        //~ MONO_ITEM fn mod1::mod1::user @@ extern_generic-mod1-mod1[External]
+        pub fn user() {
             let _ = cgu_generic_function::foo("abc");
         }
     }
 }
 
-mod mod2 {
-    use cgu_generic_function;
-
-    //~ MONO_ITEM fn mod2::user @@ extern_generic-mod2[Internal]
-    fn user() {
-        let _ = cgu_generic_function::foo("abc");
-    }
-}
-
-mod mod3 {
-    //~ MONO_ITEM fn mod3::non_user @@ extern_generic-mod3[Internal]
-    fn non_user() {}
-}
-
-// Make sure the two generic functions from the extern crate get instantiated
-// once for the current crate
 //~ MONO_ITEM fn cgu_generic_function::foo::<&str> @@ cgu_generic_function-in-extern_generic.volatile[External]
 //~ MONO_ITEM fn cgu_generic_function::bar::<&str> @@ cgu_generic_function-in-extern_generic.volatile[External]
diff --git a/tests/codegen-units/partitioning/incremental-merging.rs b/tests/codegen-units/partitioning/incremental-merging.rs
index 6834bb2bebf5c..68eee803e5f22 100644
--- a/tests/codegen-units/partitioning/incremental-merging.rs
+++ b/tests/codegen-units/partitioning/incremental-merging.rs
@@ -1,7 +1,5 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Ccodegen-units=3
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -Ccodegen-units=3
 
 #![crate_type = "rlib"]
 
@@ -9,8 +7,9 @@
 // compilation but at the same time does not modify names of CGUs that were not
 // affected by merging.
 //
-// We expect CGUs `aaa` and `bbb` to be merged (because they are the smallest),
-// while `ccc` and `ddd` are supposed to stay untouched.
+// CGU partitioning creates one CGU per module, so with 4 modules and codegen-units=3,
+// two of the modules should be merged. We expect CGUs `aaa` and `bbb` to be merged
+// (because they are the smallest), while `ccc` and `ddd` should stay untouched.
 
 pub mod aaa {
     //~ MONO_ITEM fn aaa::foo @@ incremental_merging-aaa--incremental_merging-bbb[External]
diff --git a/tests/codegen-units/partitioning/inline-always.rs b/tests/codegen-units/partitioning/inline-always.rs
new file mode 100644
index 0000000000000..5e8cce0ac337b
--- /dev/null
+++ b/tests/codegen-units/partitioning/inline-always.rs
@@ -0,0 +1,38 @@
+//@ incremental
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
+
+#![crate_type = "lib"]
+
+// This test checks that a monomorphic inline(always) function is instantiated in every CGU that
+// references it, even though this is an unoptimized incremental build.
+// It also checks that an inline(always) function is only placed in CGUs that reference it.
+
+mod inline {
+    //~ MONO_ITEM fn inline::inlined_function @@ inline_always-user1[Internal] inline_always-user2[Internal]
+    #[inline(always)]
+    pub fn inlined_function() {}
+}
+
+pub mod user1 {
+    use super::inline;
+
+    //~ MONO_ITEM fn user1::foo @@ inline_always-user1[External]
+    pub fn foo() {
+        inline::inlined_function();
+    }
+}
+
+pub mod user2 {
+    use super::inline;
+
+    //~ MONO_ITEM fn user2::bar @@ inline_always-user2[External]
+    pub fn bar() {
+        inline::inlined_function();
+    }
+}
+
+pub mod non_user {
+
+    //~ MONO_ITEM fn non_user::baz @@ inline_always-non_user[External]
+    pub fn baz() {}
+}
diff --git a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs
index b007ffe1cb510..d321c88d03a6e 100644
--- a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs
+++ b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs
@@ -1,7 +1,5 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Zinline-in-all-cgus
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=1
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen-units/partitioning/local-drop-glue.rs b/tests/codegen-units/partitioning/local-drop-glue.rs
index 5fa1df95cbc82..240f64e4f7021 100644
--- a/tests/codegen-units/partitioning/local-drop-glue.rs
+++ b/tests/codegen-units/partitioning/local-drop-glue.rs
@@ -1,14 +1,14 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
-// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Zinline-in-all-cgus -Copt-level=0
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
-#![allow(dead_code)]
 #![crate_type = "rlib"]
 
+// This test checks that drop glue is generated for types defined in this crate, and that all drop
+// glue is put in the fallback CGU.
+// This is rather similar to extern-drop-glue.rs.
+
 //~ MONO_ITEM fn std::ptr::drop_in_place::<Struct> - shim(Some(Struct)) @@ local_drop_glue-fallback.cgu[External]
-struct Struct {
+pub struct Struct {
     _a: u32,
 }
 
@@ -18,7 +18,7 @@ impl Drop for Struct {
 }
 
 //~ MONO_ITEM fn std::ptr::drop_in_place::<Outer> - shim(Some(Outer)) @@ local_drop_glue-fallback.cgu[External]
-struct Outer {
+pub struct Outer {
     _a: Struct,
 }
 
@@ -33,7 +33,7 @@ pub mod mod1 {
     //~ MONO_ITEM fn std::ptr::drop_in_place::<mod1::Struct2> - shim(Some(mod1::Struct2)) @@ local_drop_glue-fallback.cgu[External]
     struct Struct2 {
         _a: Struct,
-        //~ MONO_ITEM fn std::ptr::drop_in_place::<(u32, Struct)> - shim(Some((u32, Struct))) @@ local_drop_glue-fallback.cgu[Internal]
+        //~ MONO_ITEM fn std::ptr::drop_in_place::<(u32, Struct)> - shim(Some((u32, Struct))) @@ local_drop_glue-fallback.cgu[External]
         _b: (u32, Struct),
     }
 
diff --git a/tests/codegen-units/partitioning/local-generic.rs b/tests/codegen-units/partitioning/local-generic.rs
index 0cfc572650c1f..177eb2632f640 100644
--- a/tests/codegen-units/partitioning/local-generic.rs
+++ b/tests/codegen-units/partitioning/local-generic.rs
@@ -1,10 +1,11 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=eager
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
-#![allow(dead_code)]
 #![crate_type = "lib"]
 
+// This test checks that all the instantiations of a local generic fn are placed in the same CGU,
+// regardless of where it is called.
+
 //~ MONO_ITEM fn generic::<u32> @@ local_generic.volatile[External]
 //~ MONO_ITEM fn generic::<u64> @@ local_generic.volatile[External]
 //~ MONO_ITEM fn generic::<char> @@ local_generic.volatile[External]
@@ -13,34 +14,34 @@ pub fn generic<T>(x: T) -> T {
     x
 }
 
-//~ MONO_ITEM fn user @@ local_generic[Internal]
-fn user() {
+//~ MONO_ITEM fn user @@ local_generic[External]
+pub fn user() {
     let _ = generic(0u32);
 }
 
-mod mod1 {
+pub mod mod1 {
     pub use super::generic;
 
-    //~ MONO_ITEM fn mod1::user @@ local_generic-mod1[Internal]
-    fn user() {
+    //~ MONO_ITEM fn mod1::user @@ local_generic-mod1[External]
+    pub fn user() {
         let _ = generic(0u64);
     }
 
-    mod mod1 {
+    pub mod mod1 {
         use super::generic;
 
-        //~ MONO_ITEM fn mod1::mod1::user @@ local_generic-mod1-mod1[Internal]
-        fn user() {
+        //~ MONO_ITEM fn mod1::mod1::user @@ local_generic-mod1-mod1[External]
+        pub fn user() {
             let _ = generic('c');
         }
     }
 }
 
-mod mod2 {
+pub mod mod2 {
     use super::generic;
 
-    //~ MONO_ITEM fn mod2::user @@ local_generic-mod2[Internal]
-    fn user() {
+    //~ MONO_ITEM fn mod2::user @@ local_generic-mod2[External]
+    pub fn user() {
         let _ = generic("abc");
     }
 }
diff --git a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs b/tests/codegen-units/partitioning/local-inlining-but-not-all.rs
deleted file mode 100644
index 454de255254a4..0000000000000
--- a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
-//@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Zinline-in-all-cgus=no
-
-#![allow(dead_code)]
-#![crate_type = "lib"]
-
-mod inline {
-
-    //~ MONO_ITEM fn inline::inlined_function @@ local_inlining_but_not_all-inline[External]
-    #[inline]
-    pub fn inlined_function() {}
-}
-
-pub mod user1 {
-    use super::inline;
-
-    //~ MONO_ITEM fn user1::foo @@ local_inlining_but_not_all-user1[External]
-    pub fn foo() {
-        inline::inlined_function();
-    }
-}
-
-pub mod user2 {
-    use super::inline;
-
-    //~ MONO_ITEM fn user2::bar @@ local_inlining_but_not_all-user2[External]
-    pub fn bar() {
-        inline::inlined_function();
-    }
-}
-
-pub mod non_user {
-
-    //~ MONO_ITEM fn non_user::baz @@ local_inlining_but_not_all-non_user[External]
-    pub fn baz() {}
-}
diff --git a/tests/codegen-units/partitioning/local-inlining.rs b/tests/codegen-units/partitioning/local-inlining.rs
deleted file mode 100644
index 42c68b5c62186..0000000000000
--- a/tests/codegen-units/partitioning/local-inlining.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
-//@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Zinline-in-all-cgus
-
-#![allow(dead_code)]
-#![crate_type = "lib"]
-
-mod inline {
-
-    // Important: This function should show up in all codegen units where it is inlined
-    //~ MONO_ITEM fn inline::inlined_function @@ local_inlining-user1[Internal] local_inlining-user2[Internal]
-    #[inline(always)]
-    pub fn inlined_function() {}
-}
-
-pub mod user1 {
-    use super::inline;
-
-    //~ MONO_ITEM fn user1::foo @@ local_inlining-user1[External]
-    pub fn foo() {
-        inline::inlined_function();
-    }
-}
-
-pub mod user2 {
-    use super::inline;
-
-    //~ MONO_ITEM fn user2::bar @@ local_inlining-user2[External]
-    pub fn bar() {
-        inline::inlined_function();
-    }
-}
-
-pub mod non_user {
-
-    //~ MONO_ITEM fn non_user::baz @@ local_inlining-non_user[External]
-    pub fn baz() {}
-}
diff --git a/tests/codegen-units/partitioning/local-transitive-inlining.rs b/tests/codegen-units/partitioning/local-transitive-inlining.rs
index 0d279ebe74041..bcd32bd2e264e 100644
--- a/tests/codegen-units/partitioning/local-transitive-inlining.rs
+++ b/tests/codegen-units/partitioning/local-transitive-inlining.rs
@@ -1,11 +1,13 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Zinline-in-all-cgus
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
-#![allow(dead_code)]
 #![crate_type = "rlib"]
 
+// This test checks that a monomorphic inline(always) function is instantiated in every CGU that
+// references it, even if it is only referenced via another module.
+// The modules `inline` and `direct_user` do not get CGUs because they only define inline(always)
+// functions, which always get lazy codegen.
+
 mod inline {
 
     //~ MONO_ITEM fn inline::inlined_function @@ local_transitive_inlining-indirect_user[Internal]
@@ -13,7 +15,7 @@ mod inline {
     pub fn inlined_function() {}
 }
 
-mod direct_user {
+pub mod direct_user {
     use super::inline;
 
     //~ MONO_ITEM fn direct_user::foo @@ local_transitive_inlining-indirect_user[Internal]
diff --git a/tests/codegen-units/partitioning/methods-are-with-self-type.rs b/tests/codegen-units/partitioning/methods-are-with-self-type.rs
index 94d06829c6c35..4d3f946fd9538 100644
--- a/tests/codegen-units/partitioning/methods-are-with-self-type.rs
+++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs
@@ -1,9 +1,11 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
 #![crate_type = "lib"]
 
+// This test ensures that methods are assigned to the module where their self-type is defined, not
+// where the method is defined.
+
 pub struct SomeType;
 
 struct SomeGenericType<T1, T2>(T1, T2);
diff --git a/tests/codegen-units/partitioning/regular-modules.rs b/tests/codegen-units/partitioning/regular-modules.rs
index 2949714641557..d59074e7e3471 100644
--- a/tests/codegen-units/partitioning/regular-modules.rs
+++ b/tests/codegen-units/partitioning/regular-modules.rs
@@ -1,71 +1,71 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=eager
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
-#![allow(dead_code)]
 #![crate_type = "lib"]
 
-//~ MONO_ITEM fn foo @@ regular_modules[Internal]
-fn foo() {}
+// This test ensures that regular fn items and statics are assigned to the CGU of their module.
 
-//~ MONO_ITEM fn bar @@ regular_modules[Internal]
-fn bar() {}
+//~ MONO_ITEM fn foo @@ regular_modules[External]
+pub fn foo() {}
 
-//~ MONO_ITEM static BAZ @@ regular_modules[Internal]
-static BAZ: u64 = 0;
+//~ MONO_ITEM fn bar @@ regular_modules[External]
+pub fn bar() {}
 
-mod mod1 {
+//~ MONO_ITEM static BAZ @@ regular_modules[External]
+pub static BAZ: u64 = 0;
 
-    //~ MONO_ITEM fn mod1::foo @@ regular_modules-mod1[Internal]
-    fn foo() {}
-    //~ MONO_ITEM fn mod1::bar @@ regular_modules-mod1[Internal]
-    fn bar() {}
-    //~ MONO_ITEM static mod1::BAZ @@ regular_modules-mod1[Internal]
-    static BAZ: u64 = 0;
+pub mod mod1 {
 
-    mod mod1 {
-        //~ MONO_ITEM fn mod1::mod1::foo @@ regular_modules-mod1-mod1[Internal]
-        fn foo() {}
-        //~ MONO_ITEM fn mod1::mod1::bar @@ regular_modules-mod1-mod1[Internal]
-        fn bar() {}
-        //~ MONO_ITEM static mod1::mod1::BAZ @@ regular_modules-mod1-mod1[Internal]
-        static BAZ: u64 = 0;
+    //~ MONO_ITEM fn mod1::foo @@ regular_modules-mod1[External]
+    pub fn foo() {}
+    //~ MONO_ITEM fn mod1::bar @@ regular_modules-mod1[External]
+    pub fn bar() {}
+    //~ MONO_ITEM static mod1::BAZ @@ regular_modules-mod1[External]
+    pub static BAZ: u64 = 0;
+
+    pub mod mod1 {
+        //~ MONO_ITEM fn mod1::mod1::foo @@ regular_modules-mod1-mod1[External]
+        pub fn foo() {}
+        //~ MONO_ITEM fn mod1::mod1::bar @@ regular_modules-mod1-mod1[External]
+        pub fn bar() {}
+        //~ MONO_ITEM static mod1::mod1::BAZ @@ regular_modules-mod1-mod1[External]
+        pub static BAZ: u64 = 0;
     }
 
-    mod mod2 {
-        //~ MONO_ITEM fn mod1::mod2::foo @@ regular_modules-mod1-mod2[Internal]
-        fn foo() {}
-        //~ MONO_ITEM fn mod1::mod2::bar @@ regular_modules-mod1-mod2[Internal]
-        fn bar() {}
-        //~ MONO_ITEM static mod1::mod2::BAZ @@ regular_modules-mod1-mod2[Internal]
-        static BAZ: u64 = 0;
+    pub mod mod2 {
+        //~ MONO_ITEM fn mod1::mod2::foo @@ regular_modules-mod1-mod2[External]
+        pub fn foo() {}
+        //~ MONO_ITEM fn mod1::mod2::bar @@ regular_modules-mod1-mod2[External]
+        pub fn bar() {}
+        //~ MONO_ITEM static mod1::mod2::BAZ @@ regular_modules-mod1-mod2[External]
+        pub static BAZ: u64 = 0;
     }
 }
 
-mod mod2 {
+pub mod mod2 {
 
-    //~ MONO_ITEM fn mod2::foo @@ regular_modules-mod2[Internal]
-    fn foo() {}
-    //~ MONO_ITEM fn mod2::bar @@ regular_modules-mod2[Internal]
-    fn bar() {}
-    //~ MONO_ITEM static mod2::BAZ @@ regular_modules-mod2[Internal]
-    static BAZ: u64 = 0;
+    //~ MONO_ITEM fn mod2::foo @@ regular_modules-mod2[External]
+    pub fn foo() {}
+    //~ MONO_ITEM fn mod2::bar @@ regular_modules-mod2[External]
+    pub fn bar() {}
+    //~ MONO_ITEM static mod2::BAZ @@ regular_modules-mod2[External]
+    pub static BAZ: u64 = 0;
 
-    mod mod1 {
-        //~ MONO_ITEM fn mod2::mod1::foo @@ regular_modules-mod2-mod1[Internal]
-        fn foo() {}
-        //~ MONO_ITEM fn mod2::mod1::bar @@ regular_modules-mod2-mod1[Internal]
-        fn bar() {}
-        //~ MONO_ITEM static mod2::mod1::BAZ @@ regular_modules-mod2-mod1[Internal]
-        static BAZ: u64 = 0;
+    pub mod mod1 {
+        //~ MONO_ITEM fn mod2::mod1::foo @@ regular_modules-mod2-mod1[External]
+        pub fn foo() {}
+        //~ MONO_ITEM fn mod2::mod1::bar @@ regular_modules-mod2-mod1[External]
+        pub fn bar() {}
+        //~ MONO_ITEM static mod2::mod1::BAZ @@ regular_modules-mod2-mod1[External]
+        pub static BAZ: u64 = 0;
     }
 
-    mod mod2 {
-        //~ MONO_ITEM fn mod2::mod2::foo @@ regular_modules-mod2-mod2[Internal]
-        fn foo() {}
-        //~ MONO_ITEM fn mod2::mod2::bar @@ regular_modules-mod2-mod2[Internal]
-        fn bar() {}
-        //~ MONO_ITEM static mod2::mod2::BAZ @@ regular_modules-mod2-mod2[Internal]
-        static BAZ: u64 = 0;
+    pub mod mod2 {
+        //~ MONO_ITEM fn mod2::mod2::foo @@ regular_modules-mod2-mod2[External]
+        pub fn foo() {}
+        //~ MONO_ITEM fn mod2::mod2::bar @@ regular_modules-mod2-mod2[External]
+        pub fn bar() {}
+        //~ MONO_ITEM static mod2::mod2::BAZ @@ regular_modules-mod2-mod2[External]
+        pub static BAZ: u64 = 0;
     }
 }
diff --git a/tests/codegen-units/partitioning/shared-generics.rs b/tests/codegen-units/partitioning/shared-generics.rs
index ea312719ac918..b5bf376a6134a 100644
--- a/tests/codegen-units/partitioning/shared-generics.rs
+++ b/tests/codegen-units/partitioning/shared-generics.rs
@@ -2,13 +2,19 @@
 // NOTE: We always compile this test with -Copt-level=0 because higher opt-levels
 //       prevent drop-glue from participating in share-generics.
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Copt-level=0
+//@ compile-flags: -Zprint-mono-items=lazy -Zshare-generics=yes -Copt-level=0
 
 #![crate_type = "rlib"]
 
 //@ aux-build:shared_generics_aux.rs
 extern crate shared_generics_aux;
 
+// This test ensures that when a crate and a dependency are compiled with -Zshare-generics, the
+// downstream crate reuses generic instantiations from the dependency, but will still instantiate
+// its own copy when instantiating with arguments that the dependency did not.
+// Drop glue has a lot of special handling in the compiler, so we check that drop glue is also
+// shared.
+
 //~ MONO_ITEM fn foo
 pub fn foo() {
     //~ MONO_ITEM fn shared_generics_aux::generic_fn::<u16> @@ shared_generics_aux-in-shared_generics.volatile[External]
diff --git a/tests/codegen-units/partitioning/statics.rs b/tests/codegen-units/partitioning/statics.rs
index 00dd6d877e1e2..72bca4c5ed36a 100644
--- a/tests/codegen-units/partitioning/statics.rs
+++ b/tests/codegen-units/partitioning/statics.rs
@@ -1,9 +1,11 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
 #![crate_type = "rlib"]
 
+// This test ensures that statics are assigned to the correct module when they are defined inside
+// of a function.
+
 //~ MONO_ITEM static FOO @@ statics[Internal]
 static FOO: u32 = 0;
 
diff --git a/tests/codegen-units/partitioning/vtable-through-const.rs b/tests/codegen-units/partitioning/vtable-through-const.rs
index 3880bba6f6b32..fd73e3fe9238d 100644
--- a/tests/codegen-units/partitioning/vtable-through-const.rs
+++ b/tests/codegen-units/partitioning/vtable-through-const.rs
@@ -1,14 +1,11 @@
-// We specify incremental here because we want to test the partitioning for incremental compilation
 //@ incremental
-//@ compile-flags:-Zprint-mono-items=lazy
-//@ compile-flags:-Zinline-in-all-cgus
 // Need to disable optimizations to ensure consistent output across all CI runners.
-//@ compile-flags:-Copt-level=0
+//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0
 
-// This test case makes sure, that references made through constants are
-// recorded properly in the InliningMap.
+#![crate_type = "rlib"]
 
-#![crate_type = "lib"]
+// This test case makes sure that references made through constants cause trait associated methods
+// to be monomorphized when required.
 
 mod mod1 {
     struct NeedsDrop;
@@ -43,7 +40,7 @@ mod mod1 {
         x
     }
 
-    // These are referenced, so they produce mono-items (see start())
+    // These are referenced, so they produce mono-items (see main)
     pub const TRAIT1_REF: &'static Trait1 = &NeedsDrop as &Trait1;
     pub const TRAIT1_GEN_REF: &'static Trait1Gen<u8> = &NeedsDrop as &Trait1Gen<u8>;
     pub const ID_CHAR: fn(char) -> char = id::<char>;
@@ -77,9 +74,8 @@ mod mod1 {
     pub const ID_I64: fn(i64) -> i64 = id::<i64>;
 }
 
-//~ MONO_ITEM fn start
-#[no_mangle]
-pub fn start(_: isize, _: *const *const u8) -> isize {
+//~ MONO_ITEM fn main @@ vtable_through_const[External]
+pub fn main() {
     //~ MONO_ITEM fn <mod1::NeedsDrop as std::ops::Drop>::drop @@ vtable_through_const-fallback.cgu[External]
     //~ MONO_ITEM fn std::ptr::drop_in_place::<mod1::NeedsDrop> - shim(Some(mod1::NeedsDrop)) @@ vtable_through_const-fallback.cgu[External]
 
@@ -103,6 +99,4 @@ pub fn start(_: isize, _: *const *const u8) -> isize {
 
     //~ MONO_ITEM fn mod1::id::<char> @@ vtable_through_const-mod1.volatile[External]
     mod1::ID_CHAR('x');
-
-    0
 }
diff --git a/tests/codegen/i128-x86-callconv.rs b/tests/codegen/i128-x86-callconv.rs
new file mode 100644
index 0000000000000..9a9c9002fc026
--- /dev/null
+++ b/tests/codegen/i128-x86-callconv.rs
@@ -0,0 +1,79 @@
+//! Verify that Rust implements the expected calling convention for `i128`/`u128`.
+
+// Eliminate intermediate instructions during `nop` tests
+//@ compile-flags: -Copt-level=1
+
+//@ add-core-stubs
+//@ revisions: MSVC MINGW
+//@ [MSVC] needs-llvm-components: x86
+//@ [MINGW] needs-llvm-components: x86
+//@ [MSVC] compile-flags: --target x86_64-pc-windows-msvc
+//@ [MINGW] compile-flags: --target x86_64-pc-windows-gnu
+//@ [MSVC] filecheck-flags: --check-prefix=WIN
+//@ [MINGW] filecheck-flags: --check-prefix=WIN
+
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+#![feature(no_core, lang_items)]
+
+extern crate minicore;
+
+extern "C" {
+    fn extern_call(arg0: i128);
+    fn extern_ret() -> i128;
+}
+
+#[no_mangle]
+pub extern "C" fn pass(_arg0: u32, arg1: i128) {
+    // CHECK-LABEL: @pass(
+    // i128 is passed indirectly on Windows. It should load the pointer to the stack and pass
+    // a pointer to that allocation.
+    // WIN-SAME: %_arg0, ptr{{.*}} %arg1)
+    // WIN: [[PASS:%[_0-9]+]] = alloca [16 x i8], align 16
+    // WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
+    // WIN: store i128 [[LOADED]], ptr [[PASS]]
+    // WIN: call void @extern_call
+    unsafe { extern_call(arg1) };
+}
+
+// Check that we produce the correct return ABI
+#[no_mangle]
+pub extern "C" fn ret(_arg0: u32, arg1: i128) -> i128 {
+    // CHECK-LABEL: @ret(
+    // i128 is returned in xmm0 on Windows
+    // FIXME(#134288): This may change for the `-msvc` targets in the future.
+    // WIN-SAME: i32{{.*}} %_arg0, ptr{{.*}} %arg1)
+    // WIN: [[LOADED:%[_0-9]+]] = load <16 x i8>, ptr %arg1
+    // WIN-NEXT: ret <16 x i8> [[LOADED]]
+    arg1
+}
+
+// Check that we consume the correct return ABI
+#[no_mangle]
+pub extern "C" fn forward(dst: *mut i128) {
+    // CHECK-LABEL: @forward
+    // WIN-SAME: ptr{{.*}} %dst)
+    // WIN: [[RETURNED:%[_0-9]+]] = tail call <16 x i8> @extern_ret()
+    // WIN: store <16 x i8> [[RETURNED]], ptr %dst
+    // WIN: ret void
+    unsafe { *dst = extern_ret() };
+}
+
+#[repr(C)]
+struct RetAggregate {
+    a: i32,
+    b: i128,
+}
+
+#[no_mangle]
+pub extern "C" fn ret_aggregate(_arg0: u32, arg1: i128) -> RetAggregate {
+    // CHECK-LABEL: @ret_aggregate(
+    // Aggregates should also be returned indirectly
+    // WIN-SAME: ptr{{.*}}sret([32 x i8]){{.*}}[[RET:%[_0-9]+]], i32{{.*}}%_arg0, ptr{{.*}}%arg1)
+    // WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1
+    // WIN: [[GEP:%[_0-9]+]] = getelementptr{{.*}}, ptr [[RET]]
+    // WIN: store i128 [[LOADED]], ptr [[GEP]]
+    // WIN: ret void
+    RetAggregate { a: 1, b: arg1 }
+}
diff --git a/tests/run-make/sepcomp-cci-copies/cci_lib.rs b/tests/run-make/sepcomp-cci-copies/cci_lib.rs
deleted file mode 100644
index 869d4a6cd3e4e..0000000000000
--- a/tests/run-make/sepcomp-cci-copies/cci_lib.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![crate_type = "rlib"]
-
-#[inline]
-pub fn cci_fn() -> usize {
-    1234
-}
diff --git a/tests/run-make/sepcomp-cci-copies/foo.rs b/tests/run-make/sepcomp-cci-copies/foo.rs
deleted file mode 100644
index ba251fcb0ac24..0000000000000
--- a/tests/run-make/sepcomp-cci-copies/foo.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-extern crate cci_lib;
-use cci_lib::cci_fn;
-
-fn call1() -> usize {
-    cci_fn()
-}
-
-mod a {
-    use cci_lib::cci_fn;
-    pub fn call2() -> usize {
-        cci_fn()
-    }
-}
-
-mod b {
-    pub fn call3() -> usize {
-        0
-    }
-}
-
-fn main() {
-    call1();
-    a::call2();
-    b::call3();
-}
diff --git a/tests/run-make/sepcomp-cci-copies/rmake.rs b/tests/run-make/sepcomp-cci-copies/rmake.rs
deleted file mode 100644
index a66cc2872b434..0000000000000
--- a/tests/run-make/sepcomp-cci-copies/rmake.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Check that cross-crate inlined items are inlined in all compilation units
-// that refer to them, and not in any other compilation units.
-// Note that we have to pass `-C codegen-units=6` because up to two CGUs may be
-// created for each source module (see `rustc_const_eval::monomorphize::partitioning`).
-// See https://github.com/rust-lang/rust/pull/16367
-
-use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc};
-
-fn main() {
-    rustc().input("cci_lib.rs").run();
-    rustc().input("foo.rs").emit("llvm-ir").codegen_units(6).arg("-Zinline-in-all-cgus").run();
-    let re = regex::Regex::new(r#"define\ .*cci_fn"#).unwrap();
-    assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2);
-}
diff --git a/tests/run-make/sepcomp-inlining/foo.rs b/tests/run-make/sepcomp-inlining/foo.rs
deleted file mode 100644
index 9101ee691a4e0..0000000000000
--- a/tests/run-make/sepcomp-inlining/foo.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-#![crate_type = "lib"]
-
-#[inline]
-fn inlined() -> u32 {
-    1234
-}
-
-fn normal() -> u32 {
-    2345
-}
-
-mod a {
-    pub fn f() -> u32 {
-        ::inlined() + ::normal()
-    }
-}
-
-mod b {
-    pub fn f() -> u32 {
-        ::inlined() + ::normal()
-    }
-}
-
-pub fn start(_: isize, _: *const *const u8) -> isize {
-    a::f();
-    b::f();
-
-    0
-}
diff --git a/tests/run-make/sepcomp-inlining/rmake.rs b/tests/run-make/sepcomp-inlining/rmake.rs
deleted file mode 100644
index ea4a4d210cc3e..0000000000000
--- a/tests/run-make/sepcomp-inlining/rmake.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Test that #[inline] functions still get inlined across compilation unit
-// boundaries. Compilation should produce three IR files, but only the two
-// compilation units that have a usage of the #[inline] function should
-// contain a definition. Also, the non-#[inline] function should be defined
-// in only one compilation unit.
-// See https://github.com/rust-lang/rust/pull/16367
-
-use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc};
-
-fn main() {
-    rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).arg("-Zinline-in-all-cgus").run();
-    let re = regex::Regex::new(r#"define\ i32\ .*inlined"#).unwrap();
-    assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 0);
-    let re = regex::Regex::new(r#"define\ internal\ .*inlined"#).unwrap();
-    assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2);
-    let re = regex::Regex::new(r#"define\ hidden\ i32\ .*normal"#).unwrap();
-    assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 1);
-    let re = regex::Regex::new(r#"declare\ hidden\ i32\ .*normal"#).unwrap();
-    assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2);
-}
diff --git a/tests/run-make/sepcomp-separate/foo.rs b/tests/run-make/sepcomp-separate/foo.rs
deleted file mode 100644
index 169bafa9b3a50..0000000000000
--- a/tests/run-make/sepcomp-separate/foo.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-fn magic_fn() -> usize {
-    1234
-}
-
-mod a {
-    pub fn magic_fn() -> usize {
-        2345
-    }
-}
-
-mod b {
-    pub fn magic_fn() -> usize {
-        3456
-    }
-}
-
-fn main() {
-    magic_fn();
-    a::magic_fn();
-    b::magic_fn();
-}
diff --git a/tests/run-make/sepcomp-separate/rmake.rs b/tests/run-make/sepcomp-separate/rmake.rs
deleted file mode 100644
index 49958044a612a..0000000000000
--- a/tests/run-make/sepcomp-separate/rmake.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Test that separate compilation actually puts code into separate compilation
-// units.  `foo.rs` defines `magic_fn` in three different modules, which should
-// wind up in three different compilation units.
-// See https://github.com/rust-lang/rust/pull/16367
-
-use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc};
-
-fn main() {
-    rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).run();
-    let re = regex::Regex::new(r#"define\ .*magic_fn"#).unwrap();
-    assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 3);
-}
diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.fixed b/tests/ui/parser/bad-fn-ptr-qualifier.fixed
index e2a2f9486b785..8a97a2f09ccab 100644
--- a/tests/ui/parser/bad-fn-ptr-qualifier.fixed
+++ b/tests/ui/parser/bad-fn-ptr-qualifier.fixed
@@ -2,24 +2,24 @@
 //@ edition:2018
 // Most of items are taken from ./recover-const-async-fn-ptr.rs but this is able to apply rustfix.
 
-pub type T0 =  fn(); //~ ERROR an `fn` pointer type cannot be `const`
-pub type T1 =  extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
-pub type T2 =  unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
-pub type T3 =  fn(); //~ ERROR an `fn` pointer type cannot be `async`
-pub type T4 =  extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
-pub type T5 =  unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
-pub type T6 =   unsafe extern "C" fn();
+pub type T0 = fn(); //~ ERROR an `fn` pointer type cannot be `const`
+pub type T1 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
+pub type T2 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
+pub type T3 = fn(); //~ ERROR an `fn` pointer type cannot be `async`
+pub type T4 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
+pub type T5 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
+pub type T6 = unsafe extern "C" fn();
 //~^ ERROR an `fn` pointer type cannot be `const`
 //~| ERROR an `fn` pointer type cannot be `async`
 
-pub type FTT0 = for<'a>  fn(); //~ ERROR an `fn` pointer type cannot be `const`
-pub type FTT1 = for<'a>  extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
-pub type FTT2 = for<'a>  unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
-pub type FTT3 = for<'a>  fn(); //~ ERROR an `fn` pointer type cannot be `async`
-pub type FTT4 = for<'a>  extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
-pub type FTT5 = for<'a>  unsafe extern "C" fn();
+pub type FTT0 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `const`
+pub type FTT1 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
+pub type FTT2 = for<'a> unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
+pub type FTT3 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `async`
+pub type FTT4 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
+pub type FTT5 = for<'a> unsafe extern "C" fn();
 //~^ ERROR an `fn` pointer type cannot be `async`
-pub type FTT6 = for<'a>   unsafe extern "C" fn();
+pub type FTT6 = for<'a> unsafe extern "C" fn();
 //~^ ERROR an `fn` pointer type cannot be `const`
 //~| ERROR an `fn` pointer type cannot be `async`
 
diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.stderr b/tests/ui/parser/bad-fn-ptr-qualifier.stderr
index ddc8bac678cfb..b9d2625d9f4be 100644
--- a/tests/ui/parser/bad-fn-ptr-qualifier.stderr
+++ b/tests/ui/parser/bad-fn-ptr-qualifier.stderr
@@ -9,7 +9,7 @@ LL | pub type T0 = const fn();
 help: remove the `const` qualifier
    |
 LL - pub type T0 = const fn();
-LL + pub type T0 =  fn();
+LL + pub type T0 = fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -23,7 +23,7 @@ LL | pub type T1 = const extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - pub type T1 = const extern "C" fn();
-LL + pub type T1 =  extern "C" fn();
+LL + pub type T1 = extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -37,7 +37,7 @@ LL | pub type T2 = const unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - pub type T2 = const unsafe extern "C" fn();
-LL + pub type T2 =  unsafe extern "C" fn();
+LL + pub type T2 = unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -51,7 +51,7 @@ LL | pub type T3 = async fn();
 help: remove the `async` qualifier
    |
 LL - pub type T3 = async fn();
-LL + pub type T3 =  fn();
+LL + pub type T3 = fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -65,7 +65,7 @@ LL | pub type T4 = async extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - pub type T4 = async extern "C" fn();
-LL + pub type T4 =  extern "C" fn();
+LL + pub type T4 = extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -79,7 +79,7 @@ LL | pub type T5 = async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - pub type T5 = async unsafe extern "C" fn();
-LL + pub type T5 =  unsafe extern "C" fn();
+LL + pub type T5 = unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -93,7 +93,7 @@ LL | pub type T6 = const async unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - pub type T6 = const async unsafe extern "C" fn();
-LL + pub type T6 =  async unsafe extern "C" fn();
+LL + pub type T6 = async unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -107,7 +107,7 @@ LL | pub type T6 = const async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - pub type T6 = const async unsafe extern "C" fn();
-LL + pub type T6 = const  unsafe extern "C" fn();
+LL + pub type T6 = const unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -121,7 +121,7 @@ LL | pub type FTT0 = for<'a> const fn();
 help: remove the `const` qualifier
    |
 LL - pub type FTT0 = for<'a> const fn();
-LL + pub type FTT0 = for<'a>  fn();
+LL + pub type FTT0 = for<'a> fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -135,7 +135,7 @@ LL | pub type FTT1 = for<'a> const extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - pub type FTT1 = for<'a> const extern "C" fn();
-LL + pub type FTT1 = for<'a>  extern "C" fn();
+LL + pub type FTT1 = for<'a> extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -149,7 +149,7 @@ LL | pub type FTT2 = for<'a> const unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - pub type FTT2 = for<'a> const unsafe extern "C" fn();
-LL + pub type FTT2 = for<'a>  unsafe extern "C" fn();
+LL + pub type FTT2 = for<'a> unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -163,7 +163,7 @@ LL | pub type FTT3 = for<'a> async fn();
 help: remove the `async` qualifier
    |
 LL - pub type FTT3 = for<'a> async fn();
-LL + pub type FTT3 = for<'a>  fn();
+LL + pub type FTT3 = for<'a> fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -177,7 +177,7 @@ LL | pub type FTT4 = for<'a> async extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - pub type FTT4 = for<'a> async extern "C" fn();
-LL + pub type FTT4 = for<'a>  extern "C" fn();
+LL + pub type FTT4 = for<'a> extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -191,7 +191,7 @@ LL | pub type FTT5 = for<'a> async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - pub type FTT5 = for<'a> async unsafe extern "C" fn();
-LL + pub type FTT5 = for<'a>  unsafe extern "C" fn();
+LL + pub type FTT5 = for<'a> unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -205,7 +205,7 @@ LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - pub type FTT6 = for<'a> const async unsafe extern "C" fn();
-LL + pub type FTT6 = for<'a>  async unsafe extern "C" fn();
+LL + pub type FTT6 = for<'a> async unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -219,7 +219,7 @@ LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - pub type FTT6 = for<'a> const async unsafe extern "C" fn();
-LL + pub type FTT6 = for<'a> const  unsafe extern "C" fn();
+LL + pub type FTT6 = for<'a> const unsafe extern "C" fn();
    |
 
 error: aborting due to 16 previous errors
diff --git a/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr
index 9112a0e135a50..4e5927914ccb5 100644
--- a/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr
+++ b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr
@@ -9,7 +9,7 @@ LL | type T0 = const fn();
 help: remove the `const` qualifier
    |
 LL - type T0 = const fn();
-LL + type T0 =  fn();
+LL + type T0 = fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -23,7 +23,7 @@ LL | type T1 = const extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - type T1 = const extern "C" fn();
-LL + type T1 =  extern "C" fn();
+LL + type T1 = extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -37,7 +37,7 @@ LL | type T2 = const unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - type T2 = const unsafe extern "C" fn();
-LL + type T2 =  unsafe extern "C" fn();
+LL + type T2 = unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -51,7 +51,7 @@ LL | type T3 = async fn();
 help: remove the `async` qualifier
    |
 LL - type T3 = async fn();
-LL + type T3 =  fn();
+LL + type T3 = fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -65,7 +65,7 @@ LL | type T4 = async extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - type T4 = async extern "C" fn();
-LL + type T4 =  extern "C" fn();
+LL + type T4 = extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -79,7 +79,7 @@ LL | type T5 = async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - type T5 = async unsafe extern "C" fn();
-LL + type T5 =  unsafe extern "C" fn();
+LL + type T5 = unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -93,7 +93,7 @@ LL | type T6 = const async unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - type T6 = const async unsafe extern "C" fn();
-LL + type T6 =  async unsafe extern "C" fn();
+LL + type T6 = async unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -107,7 +107,7 @@ LL | type T6 = const async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - type T6 = const async unsafe extern "C" fn();
-LL + type T6 = const  unsafe extern "C" fn();
+LL + type T6 = const unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -121,7 +121,7 @@ LL | type FT0 = for<'a> const fn();
 help: remove the `const` qualifier
    |
 LL - type FT0 = for<'a> const fn();
-LL + type FT0 = for<'a>  fn();
+LL + type FT0 = for<'a> fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -135,7 +135,7 @@ LL | type FT1 = for<'a> const extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - type FT1 = for<'a> const extern "C" fn();
-LL + type FT1 = for<'a>  extern "C" fn();
+LL + type FT1 = for<'a> extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -149,7 +149,7 @@ LL | type FT2 = for<'a> const unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - type FT2 = for<'a> const unsafe extern "C" fn();
-LL + type FT2 = for<'a>  unsafe extern "C" fn();
+LL + type FT2 = for<'a> unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -163,7 +163,7 @@ LL | type FT3 = for<'a> async fn();
 help: remove the `async` qualifier
    |
 LL - type FT3 = for<'a> async fn();
-LL + type FT3 = for<'a>  fn();
+LL + type FT3 = for<'a> fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -177,7 +177,7 @@ LL | type FT4 = for<'a> async extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - type FT4 = for<'a> async extern "C" fn();
-LL + type FT4 = for<'a>  extern "C" fn();
+LL + type FT4 = for<'a> extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -191,7 +191,7 @@ LL | type FT5 = for<'a> async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - type FT5 = for<'a> async unsafe extern "C" fn();
-LL + type FT5 = for<'a>  unsafe extern "C" fn();
+LL + type FT5 = for<'a> unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `const`
@@ -205,7 +205,7 @@ LL | type FT6 = for<'a> const async unsafe extern "C" fn();
 help: remove the `const` qualifier
    |
 LL - type FT6 = for<'a> const async unsafe extern "C" fn();
-LL + type FT6 = for<'a>  async unsafe extern "C" fn();
+LL + type FT6 = for<'a> async unsafe extern "C" fn();
    |
 
 error: an `fn` pointer type cannot be `async`
@@ -219,7 +219,7 @@ LL | type FT6 = for<'a> const async unsafe extern "C" fn();
 help: remove the `async` qualifier
    |
 LL - type FT6 = for<'a> const async unsafe extern "C" fn();
-LL + type FT6 = for<'a> const  unsafe extern "C" fn();
+LL + type FT6 = for<'a> const unsafe extern "C" fn();
    |
 
 error[E0308]: mismatched types
diff --git a/tests/ui/asan-odr-win/asan_odr_windows.rs b/tests/ui/sanitizer/asan_odr_windows.rs
similarity index 100%
rename from tests/ui/asan-odr-win/asan_odr_windows.rs
rename to tests/ui/sanitizer/asan_odr_windows.rs
diff --git a/tests/ui/asan-odr-win/auxiliary/asan_odr_win-2.rs b/tests/ui/sanitizer/auxiliary/asan_odr_win-2.rs
similarity index 100%
rename from tests/ui/asan-odr-win/auxiliary/asan_odr_win-2.rs
rename to tests/ui/sanitizer/auxiliary/asan_odr_win-2.rs