about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorChayim Refael Friedman <chayimfr@gmail.com>2025-02-27 14:19:54 +0200
committerChayim Refael Friedman <chayimfr@gmail.com>2025-03-06 21:00:05 +0200
commitfcb34b17e22268636a7b227ce78237b158737d39 (patch)
treeb8741be1473e74354d91740fda0c0c5994bb09ee /src
parent860637abc36c5ab3cdc1cf6a5b4130a2d8fecd03 (diff)
downloadrust-fcb34b17e22268636a7b227ce78237b158737d39.tar.gz
rust-fcb34b17e22268636a7b227ce78237b158737d39.zip
Pass the target crate in `HirFormatter`
This is required to format evaluated consts, because we need trait env, and it needs the crate (currently it uses the last crate in topological order, which is wrong, the next commit will fix that).
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs100
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs55
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs63
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs47
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs71
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/symbols.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs50
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils.rs44
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs32
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs93
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs54
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs124
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/interpret.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/navigation_target.rs61
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs55
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs20
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs41
62 files changed, 824 insertions, 499 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index 7839589994b..fb604569f43 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -15,9 +15,10 @@ use stdx::never;
 use triomphe::Arc;
 
 use crate::{
-    db::HirDatabase, generics::Generics, infer::InferenceContext, lower::ParamLoweringMode,
-    mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData, ConstScalar, ConstValue,
-    GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder,
+    db::HirDatabase, display::DisplayTarget, generics::Generics, infer::InferenceContext,
+    lower::ParamLoweringMode, mir::monomorphize_mir_body_bad, to_placeholder_idx, Const, ConstData,
+    ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
+    TyBuilder,
 };
 
 use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
@@ -62,11 +63,15 @@ impl ConstEvalError {
         f: &mut String,
         db: &dyn HirDatabase,
         span_formatter: impl Fn(span::FileId, span::TextRange) -> String,
-        edition: span::Edition,
+        display_target: DisplayTarget,
     ) -> std::result::Result<(), std::fmt::Error> {
         match self {
-            ConstEvalError::MirLowerError(e) => e.pretty_print(f, db, span_formatter, edition),
-            ConstEvalError::MirEvalError(e) => e.pretty_print(f, db, span_formatter, edition),
+            ConstEvalError::MirLowerError(e) => {
+                e.pretty_print(f, db, span_formatter, display_target)
+            }
+            ConstEvalError::MirEvalError(e) => {
+                e.pretty_print(f, db, span_formatter, display_target)
+            }
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 249170c4f3e..26a3b702297 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -10,8 +10,8 @@ use test_fixture::WithFixture;
 use test_utils::skip_slow_tests;
 
 use crate::{
-    consteval::try_const_usize, db::HirDatabase, mir::pad16, test_db::TestDB, Const, ConstScalar,
-    Interner, MemoryMap,
+    consteval::try_const_usize, db::HirDatabase, display::DisplayTarget, mir::pad16,
+    test_db::TestDB, Const, ConstScalar, Interner, MemoryMap,
 };
 
 use super::{
@@ -101,11 +101,17 @@ fn check_answer(
 fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
     let mut err = String::new();
     let span_formatter = |file, range| format!("{file:?} {range:?}");
-    let edition =
-        db.crate_graph()[*db.crate_graph().crates_in_topological_order().last().unwrap()].edition;
+    let display_target = DisplayTarget::from_crate(
+        &db,
+        *db.crate_graph().crates_in_topological_order().last().unwrap(),
+    );
     match e {
-        ConstEvalError::MirLowerError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
-        ConstEvalError::MirEvalError(e) => e.pretty_print(&mut err, &db, span_formatter, edition),
+        ConstEvalError::MirLowerError(e) => {
+            e.pretty_print(&mut err, &db, span_formatter, display_target)
+        }
+        ConstEvalError::MirEvalError(e) => {
+            e.pretty_print(&mut err, &db, span_formatter, display_target)
+        }
     }
     .unwrap();
     err
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index 59aaf85164a..cc6f4d9e52e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -16,7 +16,6 @@ use intern::sym;
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
 use rustc_pattern_analysis::constructor::Constructor;
-use span::Edition;
 use syntax::{
     ast::{self, UnaryOp},
     AstNode,
@@ -31,7 +30,7 @@ use crate::{
         self,
         pat_analysis::{self, DeconstructedPat, MatchCheckCtx, WitnessPat},
     },
-    display::HirDisplay,
+    display::{DisplayTarget, HirDisplay},
     Adjust, InferenceResult, Interner, Ty, TyExt, TyKind,
 };
 
@@ -633,24 +632,24 @@ fn missing_match_arms<'p>(
     arms_is_empty: bool,
     krate: CrateId,
 ) -> String {
-    struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, Edition);
+    struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, DisplayTarget);
     impl fmt::Display for DisplayWitness<'_, '_> {
         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            let DisplayWitness(witness, cx, edition) = *self;
+            let DisplayWitness(witness, cx, display_target) = *self;
             let pat = cx.hoist_witness_pat(witness);
-            write!(f, "{}", pat.display(cx.db, edition))
+            write!(f, "{}", pat.display(cx.db, display_target))
         }
     }
 
-    let edition = cx.db.crate_graph()[krate].edition;
     let non_empty_enum = match scrut_ty.as_adt() {
         Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(),
         _ => false,
     };
+    let display_target = DisplayTarget::from_crate(cx.db, krate);
     if arms_is_empty && !non_empty_enum {
-        format!("type `{}` is non-empty", scrut_ty.display(cx.db, edition))
+        format!("type `{}` is non-empty", scrut_ty.display(cx.db, display_target))
     } else {
-        let pat_display = |witness| DisplayWitness(witness, cx, edition);
+        let pat_display = |witness| DisplayWitness(witness, cx, display_target);
         const LIMIT: usize = 3;
         match &*witnesses {
             [witness] => format!("`{}` not covered", pat_display(witness)),
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 b3613b372bf..41152d90220 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -88,6 +88,7 @@ pub struct HirFormatter<'a> {
     show_container_bounds: bool,
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
+    display_kind: DisplayKind,
     display_target: DisplayTarget,
     bounds_formatting_ctx: BoundsFormattingCtx,
 }
@@ -165,6 +166,7 @@ pub trait HirDisplay {
         limited_size: Option<usize>,
         omit_verbose_types: bool,
         display_target: DisplayTarget,
+        display_kind: DisplayKind,
         closure_style: ClosureStyle,
         show_container_bounds: bool,
     ) -> HirDisplayWrapper<'a, Self>
@@ -172,7 +174,7 @@ pub trait HirDisplay {
         Self: Sized,
     {
         assert!(
-            !matches!(display_target, DisplayTarget::SourceCode { .. }),
+            !matches!(display_kind, DisplayKind::SourceCode { .. }),
             "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
         );
         HirDisplayWrapper {
@@ -182,6 +184,7 @@ pub trait HirDisplay {
             limited_size,
             omit_verbose_types,
             display_target,
+            display_kind,
             closure_style,
             show_container_bounds,
         }
@@ -192,7 +195,7 @@ pub trait HirDisplay {
     fn display<'a>(
         &'a self,
         db: &'a dyn HirDatabase,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> HirDisplayWrapper<'a, Self>
     where
         Self: Sized,
@@ -204,7 +207,8 @@ pub trait HirDisplay {
             limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
-            display_target: DisplayTarget::Diagnostics { edition },
+            display_target,
+            display_kind: DisplayKind::Diagnostics,
             show_container_bounds: false,
         }
     }
@@ -215,7 +219,7 @@ pub trait HirDisplay {
         &'a self,
         db: &'a dyn HirDatabase,
         max_size: Option<usize>,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> HirDisplayWrapper<'a, Self>
     where
         Self: Sized,
@@ -227,7 +231,8 @@ pub trait HirDisplay {
             limited_size: None,
             omit_verbose_types: true,
             closure_style: ClosureStyle::ImplFn,
-            display_target: DisplayTarget::Diagnostics { edition },
+            display_target,
+            display_kind: DisplayKind::Diagnostics,
             show_container_bounds: false,
         }
     }
@@ -238,7 +243,7 @@ pub trait HirDisplay {
         &'a self,
         db: &'a dyn HirDatabase,
         limited_size: Option<usize>,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> HirDisplayWrapper<'a, Self>
     where
         Self: Sized,
@@ -250,7 +255,8 @@ pub trait HirDisplay {
             limited_size,
             omit_verbose_types: true,
             closure_style: ClosureStyle::ImplFn,
-            display_target: DisplayTarget::Diagnostics { edition },
+            display_target,
+            display_kind: DisplayKind::Diagnostics,
             show_container_bounds: false,
         }
     }
@@ -273,7 +279,8 @@ pub trait HirDisplay {
             entity_limit: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
-            display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
+            display_target: DisplayTarget::from_crate(db, module_id.krate()),
+            display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque },
             show_container_bounds: false,
             bounds_formatting_ctx: Default::default(),
         }) {
@@ -285,7 +292,11 @@ pub trait HirDisplay {
     }
 
     /// Returns a String representation of `self` for test purposes
-    fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
+    fn display_test<'a>(
+        &'a self,
+        db: &'a dyn HirDatabase,
+        display_target: DisplayTarget,
+    ) -> HirDisplayWrapper<'a, Self>
     where
         Self: Sized,
     {
@@ -296,7 +307,8 @@ pub trait HirDisplay {
             limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
-            display_target: DisplayTarget::Test,
+            display_target,
+            display_kind: DisplayKind::Test,
             show_container_bounds: false,
         }
     }
@@ -307,7 +319,7 @@ pub trait HirDisplay {
         &'a self,
         db: &'a dyn HirDatabase,
         show_container_bounds: bool,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> HirDisplayWrapper<'a, Self>
     where
         Self: Sized,
@@ -319,21 +331,20 @@ pub trait HirDisplay {
             limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
-            display_target: DisplayTarget::Diagnostics { edition },
+            display_target,
+            display_kind: DisplayKind::Diagnostics,
             show_container_bounds,
         }
     }
 }
 
 impl HirFormatter<'_> {
+    pub fn krate(&self) -> CrateId {
+        self.display_target.krate
+    }
+
     pub fn edition(&self) -> Edition {
-        match self.display_target {
-            DisplayTarget::Diagnostics { edition } => edition,
-            DisplayTarget::SourceCode { module_id, .. } => {
-                self.db.crate_graph()[module_id.krate()].edition
-            }
-            DisplayTarget::Test => Edition::CURRENT,
-        }
+        self.display_target.edition
     }
 
     pub fn write_joined<T: HirDisplay>(
@@ -395,20 +406,33 @@ impl HirFormatter<'_> {
     }
 }
 
+#[derive(Debug, Clone, Copy)]
+pub struct DisplayTarget {
+    krate: CrateId,
+    pub edition: Edition,
+}
+
+impl DisplayTarget {
+    pub fn from_crate(db: &dyn HirDatabase, krate: CrateId) -> Self {
+        let edition = db.crate_graph()[krate].edition;
+        Self { krate, edition }
+    }
+}
+
 #[derive(Clone, Copy)]
-pub enum DisplayTarget {
+pub enum DisplayKind {
     /// Display types for inlays, doc popups, autocompletion, etc...
     /// Showing `{unknown}` or not qualifying paths is fine here.
     /// There's no reason for this to fail.
-    Diagnostics { edition: Edition },
+    Diagnostics,
     /// Display types for inserting them in source files.
     /// The generated code should compile, so paths need to be qualified.
-    SourceCode { module_id: ModuleId, allow_opaque: bool },
+    SourceCode { target_module_id: ModuleId, allow_opaque: bool },
     /// Only for test purpose to keep real types
     Test,
 }
 
-impl DisplayTarget {
+impl DisplayKind {
     fn is_source_code(self) -> bool {
         matches!(self, Self::SourceCode { .. })
     }
@@ -451,6 +475,7 @@ pub struct HirDisplayWrapper<'a, T> {
     limited_size: Option<usize>,
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
+    display_kind: DisplayKind,
     display_target: DisplayTarget,
     show_container_bounds: bool,
 }
@@ -480,6 +505,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
             max_size: self.max_size,
             entity_limit: self.limited_size,
             omit_verbose_types: self.omit_verbose_types,
+            display_kind: self.display_kind,
             display_target: self.display_target,
             closure_style: self.closure_style,
             show_container_bounds: self.show_container_bounds,
@@ -534,7 +560,7 @@ impl HirDisplay for ProjectionTy {
         // if we are projection on a type parameter, check if the projection target has bounds
         // itself, if so, we render them directly as `impl Bound` instead of the less useful
         // `<Param as Trait>::Assoc`
-        if !f.display_target.is_source_code() {
+        if !f.display_kind.is_source_code() {
             if let TyKind::Placeholder(idx) = self_ty.kind(Interner) {
                 if !f.bounds_formatting_ctx.contains(self) {
                     let db = f.db;
@@ -1111,7 +1137,7 @@ impl HirDisplay for Ty {
                 let def = from_chalk(db, *def);
                 let sig = db.callable_item_signature(def).substitute(Interner, parameters);
 
-                if f.display_target.is_source_code() {
+                if f.display_kind.is_source_code() {
                     // `FnDef` is anonymous and there's no surface syntax for it. Show it as a
                     // function pointer type.
                     return sig.hir_fmt(f);
@@ -1200,8 +1226,8 @@ impl HirDisplay for Ty {
             }
             TyKind::Adt(AdtId(def_id), parameters) => {
                 f.start_location_link((*def_id).into());
-                match f.display_target {
-                    DisplayTarget::Diagnostics { .. } | DisplayTarget::Test => {
+                match f.display_kind {
+                    DisplayKind::Diagnostics { .. } | DisplayKind::Test { .. } => {
                         let name = match *def_id {
                             hir_def::AdtId::StructId(it) => db.struct_data(it).name.clone(),
                             hir_def::AdtId::UnionId(it) => db.union_data(it).name.clone(),
@@ -1209,7 +1235,7 @@ impl HirDisplay for Ty {
                         };
                         write!(f, "{}", name.display(f.db.upcast(), f.edition()))?;
                     }
-                    DisplayTarget::SourceCode { module_id, allow_opaque: _ } => {
+                    DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => {
                         if let Some(path) = find_path::find_path(
                             db.upcast(),
                             ItemInNs::Types((*def_id).into()),
@@ -1248,7 +1274,7 @@ impl HirDisplay for Ty {
                 let type_alias_data = db.type_alias_data(type_alias);
 
                 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
-                if f.display_target.is_test() {
+                if f.display_kind.is_test() {
                     f.start_location_link(trait_.into());
                     write!(f, "{}", trait_data.name.display(f.db.upcast(), f.edition()))?;
                     f.end_location_link();
@@ -1277,7 +1303,7 @@ impl HirDisplay for Ty {
                 f.end_location_link();
             }
             TyKind::OpaqueType(opaque_ty_id, parameters) => {
-                if !f.display_target.allows_opaque() {
+                if !f.display_kind.allows_opaque() {
                     return Err(HirDisplayError::DisplaySourceCodeError(
                         DisplaySourceCodeError::OpaqueType,
                     ));
@@ -1346,8 +1372,8 @@ impl HirDisplay for Ty {
                 }
             }
             TyKind::Closure(id, substs) => {
-                if f.display_target.is_source_code() {
-                    if !f.display_target.allows_opaque() {
+                if f.display_kind.is_source_code() {
+                    if !f.display_kind.allows_opaque() {
                         return Err(HirDisplayError::DisplaySourceCodeError(
                             DisplaySourceCodeError::OpaqueType,
                         ));
@@ -1467,7 +1493,7 @@ impl HirDisplay for Ty {
             }
             TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
             TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
-                if !f.display_target.allows_opaque() {
+                if !f.display_kind.allows_opaque() {
                     return Err(HirDisplayError::DisplaySourceCodeError(
                         DisplaySourceCodeError::OpaqueType,
                     ));
@@ -1510,7 +1536,7 @@ impl HirDisplay for Ty {
                 };
             }
             TyKind::Error => {
-                if f.display_target.is_source_code() {
+                if f.display_kind.is_source_code() {
                     f.write_char('_')?;
                 } else {
                     write!(f, "{{unknown}}")?;
@@ -1518,7 +1544,7 @@ impl HirDisplay for Ty {
             }
             TyKind::InferenceVar(..) => write!(f, "_")?,
             TyKind::Coroutine(_, subst) => {
-                if f.display_target.is_source_code() {
+                if f.display_kind.is_source_code() {
                     return Err(HirDisplayError::DisplaySourceCodeError(
                         DisplaySourceCodeError::Coroutine,
                     ));
@@ -1575,7 +1601,7 @@ fn generic_args_sans_defaults<'ga>(
     generic_def: Option<hir_def::GenericDefId>,
     parameters: &'ga [GenericArg],
 ) -> &'ga [GenericArg] {
-    if f.display_target.is_source_code() || f.omit_verbose_types() {
+    if f.display_kind.is_source_code() || f.omit_verbose_types() {
         match generic_def
             .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
             .filter(|it| !it.is_empty())
@@ -1960,7 +1986,7 @@ impl HirDisplay for LifetimeData {
                 write!(f, "{}", param_data.name.display(f.db.upcast(), f.edition()))?;
                 Ok(())
             }
-            _ if f.display_target.is_source_code() => write!(f, "'_"),
+            _ if f.display_kind.is_source_code() => write!(f, "'_"),
             LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
             LifetimeData::InferenceVar(_) => write!(f, "_"),
             LifetimeData::Static => write!(f, "'static"),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 707c4377726..2f9245a3326 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -76,13 +76,15 @@ use intern::{sym, Symbol};
 use la_arena::{Arena, Idx};
 use mir::{MirEvalError, VTableMap};
 use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
-use span::Edition;
 use syntax::ast::{make, ConstArg};
 use traits::FnTrait;
 use triomphe::Arc;
 
 use crate::{
-    consteval::unknown_const, db::HirDatabase, display::HirDisplay, generics::Generics,
+    consteval::unknown_const,
+    db::HirDatabase,
+    display::{DisplayTarget, HirDisplay},
+    generics::Generics,
     infer::unify::InferenceTable,
 };
 
@@ -1044,7 +1046,7 @@ where
 pub fn known_const_to_ast(
     konst: &Const,
     db: &dyn HirDatabase,
-    edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<ConstArg> {
     if let ConstValue::Concrete(c) = &konst.interned().value {
         match c.interned {
@@ -1055,7 +1057,7 @@ pub fn known_const_to_ast(
             _ => (),
         }
     }
-    Some(make::expr_const_value(konst.display(db, edition).to_string().as_str()))
+    Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str()))
 }
 
 #[derive(Debug, Copy, Clone)]
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
index 41304bbd8a9..56c431ef8da 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
@@ -5,7 +5,7 @@ use std::{collections::hash_map::Entry, fmt::Display, iter};
 use crate::{
     consteval::usize_const,
     db::HirDatabase,
-    display::HirDisplay,
+    display::{DisplayTarget, HirDisplay},
     infer::{normalize, PointerCast},
     lang_items::is_box,
     mapping::ToChalk,
@@ -168,7 +168,7 @@ impl<V, T> ProjectionElem<V, T> {
                 _ => {
                     never!(
                         "Overloaded deref on type {} is not a projection",
-                        base.display(db, db.crate_graph()[krate].edition)
+                        base.display(db, DisplayTarget::from_crate(db, krate))
                     );
                     TyKind::Error.intern(Interner)
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
index 9c86d3b59f6..fbcca388e78 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
@@ -13,6 +13,7 @@ use triomphe::Arc;
 
 use crate::{
     db::{HirDatabase, InternedClosure},
+    display::DisplayTarget,
     mir::Operand,
     utils::ClosureSubst,
     ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags,
@@ -422,7 +423,10 @@ fn ever_initialized_map(
             let Some(terminator) = &block.terminator else {
                 never!(
                     "Terminator should be none only in construction.\nThe body:\n{}",
-                    body.pretty_print(db)
+                    body.pretty_print(
+                        db,
+                        DisplayTarget::from_crate(db, body.owner.krate(db.upcast()))
+                    )
                 );
                 return;
             };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index d0f9f4519ca..74a34e29817 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -24,7 +24,7 @@ use rustc_apfloat::{
     Float,
 };
 use rustc_hash::{FxHashMap, FxHashSet};
-use span::{Edition, FileId};
+use span::FileId;
 use stdx::never;
 use syntax::{SyntaxNodePtr, TextRange};
 use triomphe::Arc;
@@ -32,7 +32,7 @@ use triomphe::Arc;
 use crate::{
     consteval::{intern_const_scalar, try_const_usize, ConstEvalError},
     db::{HirDatabase, InternedClosure},
-    display::{ClosureStyle, HirDisplay},
+    display::{ClosureStyle, DisplayTarget, HirDisplay},
     infer::PointerCast,
     layout::{Layout, LayoutError, RustcEnumVariantIdx},
     mapping::from_chalk,
@@ -359,7 +359,7 @@ impl MirEvalError {
         f: &mut String,
         db: &dyn HirDatabase,
         span_formatter: impl Fn(FileId, TextRange) -> String,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> std::result::Result<(), std::fmt::Error> {
         writeln!(f, "Mir eval error:")?;
         let mut err = self;
@@ -372,7 +372,7 @@ impl MirEvalError {
                         writeln!(
                             f,
                             "In function {} ({:?})",
-                            function_name.name.display(db.upcast(), edition),
+                            function_name.name.display(db.upcast(), display_target.edition),
                             func
                         )?;
                     }
@@ -417,7 +417,7 @@ impl MirEvalError {
                 write!(
                     f,
                     "Layout for type `{}` is not available due {err:?}",
-                    ty.display(db, edition).with_closure_style(ClosureStyle::ClosureWithId)
+                    ty.display(db, display_target).with_closure_style(ClosureStyle::ClosureWithId)
                 )?;
             }
             MirEvalError::MirLowerError(func, err) => {
@@ -428,12 +428,15 @@ impl MirEvalError {
                         let substs = generics.placeholder_subst(db);
                         db.impl_self_ty(impl_id)
                             .substitute(Interner, &substs)
-                            .display(db, edition)
+                            .display(db, display_target)
                             .to_string()
                     }),
-                    ItemContainerId::TraitId(it) => {
-                        Some(db.trait_data(it).name.display(db.upcast(), edition).to_string())
-                    }
+                    ItemContainerId::TraitId(it) => Some(
+                        db.trait_data(it)
+                            .name
+                            .display(db.upcast(), display_target.edition)
+                            .to_string(),
+                    ),
                     _ => None,
                 };
                 writeln!(
@@ -441,17 +444,17 @@ impl MirEvalError {
                     "MIR lowering for function `{}{}{}` ({:?}) failed due:",
                     self_.as_deref().unwrap_or_default(),
                     if self_.is_some() { "::" } else { "" },
-                    function_name.name.display(db.upcast(), edition),
+                    function_name.name.display(db.upcast(), display_target.edition),
                     func
                 )?;
-                err.pretty_print(f, db, span_formatter, edition)?;
+                err.pretty_print(f, db, span_formatter, display_target)?;
             }
             MirEvalError::ConstEvalError(name, err) => {
                 MirLowerError::ConstEvalError((**name).into(), err.clone()).pretty_print(
                     f,
                     db,
                     span_formatter,
-                    edition,
+                    display_target,
                 )?;
             }
             MirEvalError::UndefinedBehavior(_)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 7d3376f56be..f61ecabb7e4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -14,6 +14,7 @@ use intern::{sym, Symbol};
 use stdx::never;
 
 use crate::{
+    display::DisplayTarget,
     error_lifetime,
     mir::eval::{
         pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay,
@@ -835,8 +836,7 @@ impl Evaluator<'_> {
                     // render full paths.
                     Err(_) => {
                         let krate = locals.body.owner.krate(self.db.upcast());
-                        let edition = self.db.crate_graph()[krate].edition;
-                        ty.display(self.db, edition).to_string()
+                        ty.display(self.db, DisplayTarget::from_crate(self.db, krate)).to_string()
                     }
                 };
                 let len = ty_name.len();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
index 2b5486fc5fa..084c391d26c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
@@ -3,6 +3,7 @@ use span::{Edition, EditionedFileId};
 use syntax::{TextRange, TextSize};
 use test_fixture::WithFixture;
 
+use crate::display::DisplayTarget;
 use crate::{db::HirDatabase, mir::MirLowerError, test_db::TestDB, Interner, Substitution};
 
 use super::{interpret_mir, MirEvalError};
@@ -67,7 +68,9 @@ fn check_pass_and_stdio(
             let span_formatter = |file, range: TextRange| {
                 format!("{:?} {:?}..{:?}", file, line_index(range.start()), line_index(range.end()))
             };
-            e.pretty_print(&mut err, &db, span_formatter, Edition::CURRENT).unwrap();
+            let krate = db.module_for_file(file_id).krate();
+            e.pretty_print(&mut err, &db, span_formatter, DisplayTarget::from_crate(&db, krate))
+                .unwrap();
             panic!("Error in interpreting: {err}");
         }
         Ok((stdout, stderr)) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 2fe4ce8319e..520717e7995 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -2,7 +2,7 @@
 
 use std::{fmt::Write, iter, mem};
 
-use base_db::ra_salsa::Cycle;
+use base_db::{ra_salsa::Cycle, CrateId};
 use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
 use hir_def::{
     data::adt::{StructKind, VariantData},
@@ -29,7 +29,7 @@ use triomphe::Arc;
 use crate::{
     consteval::ConstEvalError,
     db::{HirDatabase, InternedClosure},
-    display::{hir_display_with_types_map, HirDisplay},
+    display::{hir_display_with_types_map, DisplayTarget, HirDisplay},
     error_lifetime,
     generics::generics,
     infer::{cast::CastTy, unify::InferenceTable, CaptureKind, CapturedItem, TypeMismatch},
@@ -160,17 +160,17 @@ impl MirLowerError {
         f: &mut String,
         db: &dyn HirDatabase,
         span_formatter: impl Fn(FileId, TextRange) -> String,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> std::result::Result<(), std::fmt::Error> {
         match self {
             MirLowerError::ConstEvalError(name, e) => {
                 writeln!(f, "In evaluating constant {name}")?;
                 match &**e {
                     ConstEvalError::MirLowerError(e) => {
-                        e.pretty_print(f, db, span_formatter, edition)?
+                        e.pretty_print(f, db, span_formatter, display_target)?
                     }
                     ConstEvalError::MirEvalError(e) => {
-                        e.pretty_print(f, db, span_formatter, edition)?
+                        e.pretty_print(f, db, span_formatter, display_target)?
                     }
                 }
             }
@@ -179,15 +179,15 @@ impl MirLowerError {
                 writeln!(
                     f,
                     "Missing function definition for {}",
-                    body.pretty_print_expr(db.upcast(), *owner, *it, edition)
+                    body.pretty_print_expr(db.upcast(), *owner, *it, display_target.edition)
                 )?;
             }
             MirLowerError::HasErrors => writeln!(f, "Type inference result contains errors")?,
             MirLowerError::TypeMismatch(e) => writeln!(
                 f,
                 "Type mismatch: Expected {}, found {}",
-                e.expected.display(db, edition),
-                e.actual.display(db, edition),
+                e.expected.display(db, display_target),
+                e.actual.display(db, display_target),
             )?,
             MirLowerError::GenericArgNotProvided(id, subst) => {
                 let parent = id.parent;
@@ -195,11 +195,14 @@ impl MirLowerError {
                 writeln!(
                     f,
                     "Generic arg not provided for {}",
-                    param.name().unwrap_or(&Name::missing()).display(db.upcast(), edition)
+                    param
+                        .name()
+                        .unwrap_or(&Name::missing())
+                        .display(db.upcast(), display_target.edition)
                 )?;
                 writeln!(f, "Provided args: [")?;
                 for g in subst.iter(Interner) {
-                    write!(f, "    {},", g.display(db, edition))?;
+                    write!(f, "    {},", g.display(db, display_target))?;
                 }
                 writeln!(f, "]")?;
             }
@@ -251,11 +254,11 @@ impl MirLowerError {
     fn unresolved_path(
         db: &dyn HirDatabase,
         p: &Path,
-        edition: Edition,
+        display_target: DisplayTarget,
         types_map: &TypesMap,
     ) -> Self {
         Self::UnresolvedName(
-            hir_display_with_types_map(p, types_map).display(db, edition).to_string(),
+            hir_display_with_types_map(p, types_map).display(db, display_target).to_string(),
         )
     }
 }
@@ -462,7 +465,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                             MirLowerError::unresolved_path(
                                 self.db,
                                 p,
-                                self.edition(),
+                                DisplayTarget::from_crate(self.db, self.krate()),
                                 &self.body.types,
                             )
                         })?;
@@ -838,7 +841,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     self.infer.variant_resolution_for_expr(expr_id).ok_or_else(|| match path {
                         Some(p) => MirLowerError::UnresolvedName(
                             hir_display_with_types_map(&**p, &self.body.types)
-                                .display(self.db, self.edition())
+                                .display(self.db, self.display_target())
                                 .to_string(),
                         ),
                         None => MirLowerError::RecordLiteralWithoutPath,
@@ -1362,9 +1365,16 @@ impl<'ctx> MirLowerCtx<'ctx> {
         match &self.body.exprs[*loc] {
             Expr::Literal(l) => self.lower_literal_to_operand(ty, l),
             Expr::Path(c) => {
-                let edition = self.edition();
-                let unresolved_name =
-                    || MirLowerError::unresolved_path(self.db, c, edition, &self.body.types);
+                let owner = self.owner;
+                let db = self.db;
+                let unresolved_name = || {
+                    MirLowerError::unresolved_path(
+                        self.db,
+                        c,
+                        DisplayTarget::from_crate(db, owner.krate(db.upcast())),
+                        &self.body.types,
+                    )
+                };
                 let pr = self
                     .resolver
                     .resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT)
@@ -1910,8 +1920,15 @@ impl<'ctx> MirLowerCtx<'ctx> {
     }
 
     fn edition(&self) -> Edition {
-        let krate = self.owner.krate(self.db.upcast());
-        self.db.crate_graph()[krate].edition
+        self.db.crate_graph()[self.krate()].edition
+    }
+
+    fn krate(&self) -> CrateId {
+        self.owner.krate(self.db.upcast())
+    }
+
+    fn display_target(&self) -> DisplayTarget {
+        DisplayTarget::from_crate(self.db, self.krate())
     }
 
     fn drop_until_scope(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 289175feefb..783f92b2043 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -350,7 +350,12 @@ impl MirLowerCtx<'_> {
                 )?,
                 None => {
                     let unresolved_name = || {
-                        MirLowerError::unresolved_path(self.db, p, self.edition(), &self.body.types)
+                        MirLowerError::unresolved_path(
+                            self.db,
+                            p,
+                            self.display_target(),
+                            &self.body.types,
+                        )
                     };
                     let hygiene = self.body.pat_path_hygiene(pattern);
                     let pr = self
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
index 2a26101ac43..7d7d4106cb9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
@@ -9,11 +9,10 @@ use either::Either;
 use hir_def::{expr_store::Body, hir::BindingId};
 use hir_expand::{name::Name, Lookup};
 use la_arena::ArenaMap;
-use span::Edition;
 
 use crate::{
     db::HirDatabase,
-    display::{ClosureStyle, HirDisplay},
+    display::{ClosureStyle, DisplayTarget, HirDisplay},
     mir::{PlaceElem, ProjectionElem, StatementKind, TerminatorKind},
     ClosureId,
 };
@@ -39,17 +38,21 @@ macro_rules! wln {
 }
 
 impl MirBody {
-    pub fn pretty_print(&self, db: &dyn HirDatabase) -> String {
+    pub fn pretty_print(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
         let hir_body = db.body(self.owner);
-        let mut ctx = MirPrettyCtx::new(self, &hir_body, db);
+        let mut ctx = MirPrettyCtx::new(self, &hir_body, db, display_target);
         ctx.for_body(|this| match ctx.body.owner {
             hir_def::DefWithBodyId::FunctionId(id) => {
                 let data = db.function_data(id);
-                w!(this, "fn {}() ", data.name.display(db.upcast(), Edition::LATEST));
+                w!(this, "fn {}() ", data.name.display(db.upcast(), this.display_target.edition));
             }
             hir_def::DefWithBodyId::StaticId(id) => {
                 let data = db.static_data(id);
-                w!(this, "static {}: _ = ", data.name.display(db.upcast(), Edition::LATEST));
+                w!(
+                    this,
+                    "static {}: _ = ",
+                    data.name.display(db.upcast(), this.display_target.edition)
+                );
             }
             hir_def::DefWithBodyId::ConstId(id) => {
                 let data = db.const_data(id);
@@ -59,7 +62,7 @@ impl MirBody {
                     data.name
                         .as_ref()
                         .unwrap_or(&Name::missing())
-                        .display(db.upcast(), Edition::LATEST)
+                        .display(db.upcast(), this.display_target.edition)
                 );
             }
             hir_def::DefWithBodyId::VariantId(id) => {
@@ -70,10 +73,10 @@ impl MirBody {
                     "enum {}::{} = ",
                     enum_loc.id.item_tree(db.upcast())[enum_loc.id.value]
                         .name
-                        .display(db.upcast(), Edition::LATEST),
+                        .display(db.upcast(), this.display_target.edition),
                     loc.id.item_tree(db.upcast())[loc.id.value]
                         .name
-                        .display(db.upcast(), Edition::LATEST),
+                        .display(db.upcast(), this.display_target.edition),
                 )
             }
             hir_def::DefWithBodyId::InTypeConstId(id) => {
@@ -85,14 +88,14 @@ impl MirBody {
 
     // String with lines is rendered poorly in `dbg` macros, which I use very much, so this
     // function exists to solve that.
-    pub fn dbg(&self, db: &dyn HirDatabase) -> impl Debug {
+    pub fn dbg(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> impl Debug {
         struct StringDbg(String);
         impl Debug for StringDbg {
             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                 f.write_str(&self.0)
             }
         }
-        StringDbg(self.pretty_print(db))
+        StringDbg(self.pretty_print(db, display_target))
     }
 }
 
@@ -103,6 +106,7 @@ struct MirPrettyCtx<'a> {
     result: String,
     indent: String,
     local_to_binding: ArenaMap<LocalId, BindingId>,
+    display_target: DisplayTarget,
 }
 
 impl Write for MirPrettyCtx<'_> {
@@ -182,7 +186,12 @@ impl<'a> MirPrettyCtx<'a> {
         wln!(self, "}}");
     }
 
-    fn new(body: &'a MirBody, hir_body: &'a Body, db: &'a dyn HirDatabase) -> Self {
+    fn new(
+        body: &'a MirBody,
+        hir_body: &'a Body,
+        db: &'a dyn HirDatabase,
+        display_target: DisplayTarget,
+    ) -> Self {
         let local_to_binding = body.local_to_binding_map();
         MirPrettyCtx {
             body,
@@ -191,6 +200,7 @@ impl<'a> MirPrettyCtx<'a> {
             indent: String::new(),
             local_to_binding,
             hir_body,
+            display_target,
         }
     }
 
@@ -208,7 +218,7 @@ impl<'a> MirPrettyCtx<'a> {
             wln!(
                 self,
                 "let {}: {};",
-                self.local_name(id).display_test(self.db),
+                self.local_name(id).display_test(self.db, self.display_target),
                 self.hir_display(&local.ty)
             );
         }
@@ -242,14 +252,14 @@ impl<'a> MirPrettyCtx<'a> {
                             wln!(
                                 this,
                                 "StorageDead({})",
-                                this.local_name(*p).display_test(self.db)
+                                this.local_name(*p).display_test(this.db, this.display_target)
                             );
                         }
                         StatementKind::StorageLive(p) => {
                             wln!(
                                 this,
                                 "StorageLive({})",
-                                this.local_name(*p).display_test(self.db)
+                                this.local_name(*p).display_test(this.db, this.display_target)
                             );
                         }
                         StatementKind::Deinit(p) => {
@@ -313,7 +323,7 @@ impl<'a> MirPrettyCtx<'a> {
         fn f(this: &mut MirPrettyCtx<'_>, local: LocalId, projections: &[PlaceElem]) {
             let Some((last, head)) = projections.split_last() else {
                 // no projection
-                w!(this, "{}", this.local_name(local).display_test(this.db));
+                w!(this, "{}", this.local_name(local).display_test(this.db, this.display_target));
                 return;
             };
             match last {
@@ -333,13 +343,17 @@ impl<'a> MirPrettyCtx<'a> {
                             w!(
                                 this,
                                 " as {}).{}",
-                                variant_name.display(this.db.upcast(), Edition::LATEST),
-                                name.display(this.db.upcast(), Edition::LATEST)
+                                variant_name.display(this.db.upcast(), this.display_target.edition),
+                                name.display(this.db.upcast(), this.display_target.edition)
                             );
                         }
                         hir_def::VariantId::StructId(_) | hir_def::VariantId::UnionId(_) => {
                             f(this, local, head);
-                            w!(this, ".{}", name.display(this.db.upcast(), Edition::LATEST));
+                            w!(
+                                this,
+                                ".{}",
+                                name.display(this.db.upcast(), this.display_target.edition)
+                            );
                         }
                     }
                 }
@@ -353,7 +367,11 @@ impl<'a> MirPrettyCtx<'a> {
                 }
                 ProjectionElem::Index(l) => {
                     f(this, local, head);
-                    w!(this, "[{}]", this.local_name(*l).display_test(this.db));
+                    w!(
+                        this,
+                        "[{}]",
+                        this.local_name(*l).display_test(this.db, this.display_target)
+                    );
                 }
                 it => {
                     f(this, local, head);
@@ -403,7 +421,7 @@ impl<'a> MirPrettyCtx<'a> {
             Rvalue::Repeat(op, len) => {
                 w!(self, "[");
                 self.operand(op);
-                w!(self, "; {}]", len.display_test(self.db));
+                w!(self, "; {}]", len.display_test(self.db, self.display_target));
             }
             Rvalue::Aggregate(AggregateKind::Adt(_, _), it) => {
                 w!(self, "Adt(");
@@ -478,6 +496,7 @@ impl<'a> MirPrettyCtx<'a> {
     }
 
     fn hir_display<T: HirDisplay>(&self, ty: &'a T) -> impl Display + 'a {
-        ty.display_test(self.db).with_closure_style(ClosureStyle::ClosureWithSubst)
+        ty.display_test(self.db, self.display_target)
+            .with_closure_style(ClosureStyle::ClosureWithSubst)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
index f5a4d4ff35c..81e38be2285 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -15,7 +15,7 @@ mod type_alias_impl_traits;
 use std::env;
 use std::sync::LazyLock;
 
-use base_db::SourceDatabaseFileInputExt as _;
+use base_db::{CrateId, SourceDatabaseFileInputExt as _};
 use expect_test::Expect;
 use hir_def::{
     db::DefDatabase,
@@ -41,7 +41,7 @@ use triomphe::Arc;
 
 use crate::{
     db::HirDatabase,
-    display::HirDisplay,
+    display::{DisplayTarget, HirDisplay},
     infer::{Adjustment, TypeMismatch},
     test_db::TestDB,
     InferenceResult, Ty,
@@ -124,7 +124,7 @@ fn check_impl(
     }
     assert!(had_annotations || allow_none, "no `//^` annotations found");
 
-    let mut defs: Vec<DefWithBodyId> = Vec::new();
+    let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new();
     for file_id in files {
         let module = db.module_for_file_opt(file_id);
         let module = match module {
@@ -133,16 +133,17 @@ fn check_impl(
         };
         let def_map = module.def_map(&db);
         visit_module(&db, &def_map, module.local_id, &mut |it| {
-            defs.push(match it {
+            let def = match it {
                 ModuleDefId::FunctionId(it) => it.into(),
                 ModuleDefId::EnumVariantId(it) => it.into(),
                 ModuleDefId::ConstId(it) => it.into(),
                 ModuleDefId::StaticId(it) => it.into(),
                 _ => return,
-            })
+            };
+            defs.push((def, module.krate()))
         });
     }
-    defs.sort_by_key(|def| match def {
+    defs.sort_by_key(|(def, _)| match def {
         DefWithBodyId::FunctionId(it) => {
             let loc = it.lookup(&db);
             loc.source(&db).value.syntax().text_range().start()
@@ -162,7 +163,8 @@ fn check_impl(
         DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
     });
     let mut unexpected_type_mismatches = String::new();
-    for def in defs {
+    for (def, krate) in defs {
+        let display_target = DisplayTarget::from_crate(&db, krate);
         let (body, body_source_map) = db.body_with_source_map(def);
         let inference_result = db.infer(def);
 
@@ -179,7 +181,7 @@ fn check_impl(
                 let actual = if display_source {
                     ty.display_source_code(&db, def.module(&db), true).unwrap()
                 } else {
-                    ty.display_test(&db).to_string()
+                    ty.display_test(&db, display_target).to_string()
                 };
                 assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range);
             }
@@ -195,7 +197,7 @@ fn check_impl(
                 let actual = if display_source {
                     ty.display_source_code(&db, def.module(&db), true).unwrap()
                 } else {
-                    ty.display_test(&db).to_string()
+                    ty.display_test(&db, display_target).to_string()
                 };
                 assert_eq!(actual, expected, "type annotation differs at {:#?}", range.range);
             }
@@ -224,8 +226,8 @@ fn check_impl(
             let range = node.as_ref().original_file_range_rooted(&db);
             let actual = format!(
                 "expected {}, got {}",
-                mismatch.expected.display_test(&db),
-                mismatch.actual.display_test(&db)
+                mismatch.expected.display_test(&db, display_target),
+                mismatch.actual.display_test(&db, display_target)
             );
             match mismatches.remove(&range) {
                 Some(annotation) => assert_eq!(actual, annotation),
@@ -299,7 +301,9 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
 
     let mut infer_def = |inference_result: Arc<InferenceResult>,
                          body: Arc<Body>,
-                         body_source_map: Arc<BodySourceMap>| {
+                         body_source_map: Arc<BodySourceMap>,
+                         krate: CrateId| {
+        let display_target = DisplayTarget::from_crate(&db, krate);
         let mut types: Vec<(InFile<SyntaxNode>, &Ty)> = Vec::new();
         let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = Vec::new();
 
@@ -361,7 +365,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
                 macro_prefix,
                 range,
                 ellipsize(text, 15),
-                ty.display_test(&db)
+                ty.display_test(&db, display_target)
             );
         }
         if include_mismatches {
@@ -377,8 +381,8 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
                     "{}{:?}: expected {}, got {}\n",
                     macro_prefix,
                     range,
-                    mismatch.expected.display_test(&db),
-                    mismatch.actual.display_test(&db),
+                    mismatch.expected.display_test(&db, display_target),
+                    mismatch.actual.display_test(&db, display_target),
                 );
             }
         }
@@ -387,17 +391,18 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
     let module = db.module_for_file(file_id);
     let def_map = module.def_map(&db);
 
-    let mut defs: Vec<DefWithBodyId> = Vec::new();
+    let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new();
     visit_module(&db, &def_map, module.local_id, &mut |it| {
-        defs.push(match it {
+        let def = match it {
             ModuleDefId::FunctionId(it) => it.into(),
             ModuleDefId::EnumVariantId(it) => it.into(),
             ModuleDefId::ConstId(it) => it.into(),
             ModuleDefId::StaticId(it) => it.into(),
             _ => return,
-        })
+        };
+        defs.push((def, module.krate()))
     });
-    defs.sort_by_key(|def| match def {
+    defs.sort_by_key(|(def, _)| match def {
         DefWithBodyId::FunctionId(it) => {
             let loc = it.lookup(&db);
             loc.source(&db).value.syntax().text_range().start()
@@ -416,10 +421,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
         }
         DefWithBodyId::InTypeConstId(it) => it.source(&db).syntax().text_range().start(),
     });
-    for def in defs {
+    for (def, krate) in defs {
         let (body, source_map) = db.body_with_source_map(def);
         let infer = db.infer(def);
-        infer_def(infer, body, source_map);
+        infer_def(infer, body, source_map, krate);
     }
 
     buf.truncate(buf.trim_end().len());
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
index 34d299edd1b..6f7bfc4ea7a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
@@ -8,7 +8,7 @@ use syntax::{AstNode, AstPtr};
 use test_fixture::WithFixture;
 
 use crate::db::{HirDatabase, InternedClosureId};
-use crate::display::HirDisplay;
+use crate::display::{DisplayTarget, HirDisplay};
 use crate::mir::MirSpan;
 use crate::test_db::TestDB;
 
@@ -66,7 +66,11 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
                         .join(", "),
                 };
                 let place = capture.display_place(closure.0, db);
-                let capture_ty = capture.ty.skip_binders().display_test(db).to_string();
+                let capture_ty = capture
+                    .ty
+                    .skip_binders()
+                    .display_test(db, DisplayTarget::from_crate(db, module.krate()))
+                    .to_string();
                 let spans = capture
                     .spans()
                     .iter()
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 7549d54a544..a59f90b1750 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -39,7 +39,7 @@ use std::{
 };
 
 use arrayvec::ArrayVec;
-use base_db::{CrateDisplayName, CrateId, CrateOrigin};
+use base_db::{CrateDisplayName, CrateId, CrateOrigin, LangCrateOrigin};
 use either::Either;
 use hir_def::{
     data::{adt::VariantData, TraitFlags},
@@ -147,7 +147,7 @@ pub use {
     hir_ty::{
         consteval::ConstEvalError,
         diagnostics::UnsafetyReason,
-        display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
+        display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite},
         dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
         layout::LayoutError,
         method_resolution::TyFingerprint,
@@ -282,6 +282,21 @@ impl Crate {
         let data = &db.crate_graph()[self.id];
         data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone())
     }
+
+    pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget {
+        DisplayTarget::from_crate(db, self.id)
+    }
+
+    fn core(db: &dyn HirDatabase) -> Option<Crate> {
+        let crate_graph = db.crate_graph();
+        let result = crate_graph
+            .iter()
+            .find(|&krate| {
+                matches!(crate_graph[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core))
+            })
+            .map(Crate::from);
+        result
+    }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -470,6 +485,17 @@ impl ModuleDef {
     }
 }
 
+impl HasCrate for ModuleDef {
+    fn krate(&self, db: &dyn HirDatabase) -> Crate {
+        match self.module(db) {
+            Some(module) => module.krate(),
+            None => Crate::core(db).unwrap_or_else(|| {
+                (*db.crate_graph().crates_in_topological_order().last().unwrap()).into()
+            }),
+        }
+    }
+}
+
 impl HasVisibility for ModuleDef {
     fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
         match *self {
@@ -1865,7 +1891,7 @@ impl DefWithBody {
     pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
         let body = db.mir_body(self.id());
         match body {
-            Ok(body) => body.pretty_print(db),
+            Ok(body) => body.pretty_print(db, self.module(db).krate().to_display_target(db)),
             Err(e) => format!("error:\n{e:?}"),
         }
     }
@@ -2451,8 +2477,6 @@ impl Function {
         db: &dyn HirDatabase,
         span_formatter: impl Fn(FileId, TextRange) -> String,
     ) -> Result<String, ConstEvalError> {
-        let krate = HasModule::krate(&self.id, db.upcast());
-        let edition = db.crate_graph()[krate].edition;
         let body = db.monomorphized_mir_body(
             self.id.into(),
             Substitution::empty(Interner),
@@ -2463,7 +2487,12 @@ impl Function {
             Ok(_) => "pass".to_owned(),
             Err(e) => {
                 let mut r = String::new();
-                _ = e.pretty_print(&mut r, db, &span_formatter, edition);
+                _ = e.pretty_print(
+                    &mut r,
+                    db,
+                    &span_formatter,
+                    self.krate(db).to_display_target(db),
+                );
                 r
             }
         };
@@ -2727,8 +2756,8 @@ pub struct EvaluatedConst {
 }
 
 impl EvaluatedConst {
-    pub fn render(&self, db: &dyn HirDatabase, edition: Edition) -> String {
-        format!("{}", self.const_.display(db, edition))
+    pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
+        format!("{}", self.const_.display(db, display_target))
     }
 
     pub fn render_debug(&self, db: &dyn HirDatabase) -> Result<String, MirEvalError> {
@@ -4197,9 +4226,13 @@ impl ConstParam {
         Type::new(db, self.id.parent(), db.const_param_ty(self.id))
     }
 
-    pub fn default(self, db: &dyn HirDatabase, edition: Edition) -> Option<ast::ConstArg> {
+    pub fn default(
+        self,
+        db: &dyn HirDatabase,
+        display_target: DisplayTarget,
+    ) -> Option<ast::ConstArg> {
         let arg = generic_arg_from_param(db, self.id.into())?;
-        known_const_to_ast(arg.constant(Interner)?, db, edition)
+        known_const_to_ast(arg.constant(Interner)?, db, display_target)
     }
 }
 
@@ -4507,18 +4540,18 @@ impl Closure {
         TyKind::Closure(self.id, self.subst).intern(Interner)
     }
 
-    pub fn display_with_id(&self, db: &dyn HirDatabase, edition: Edition) -> String {
+    pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
         self.clone()
             .as_ty()
-            .display(db, edition)
+            .display(db, display_target)
             .with_closure_style(ClosureStyle::ClosureWithId)
             .to_string()
     }
 
-    pub fn display_with_impl(&self, db: &dyn HirDatabase, edition: Edition) -> String {
+    pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
         self.clone()
             .as_ty()
-            .display(db, edition)
+            .display(db, display_target)
             .with_closure_style(ClosureStyle::ImplFn)
             .to_string()
     }
@@ -5323,7 +5356,7 @@ impl Type {
     pub fn type_and_const_arguments<'a>(
         &'a self,
         db: &'a dyn HirDatabase,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> impl Iterator<Item = SmolStr> + 'a {
         self.ty
             .strip_references()
@@ -5333,10 +5366,10 @@ impl Type {
             .filter_map(move |arg| {
                 // arg can be either a `Ty` or `constant`
                 if let Some(ty) = arg.ty(Interner) {
-                    Some(format_smolstr!("{}", ty.display(db, edition)))
+                    Some(format_smolstr!("{}", ty.display(db, display_target)))
                 } else {
                     arg.constant(Interner)
-                        .map(|const_| format_smolstr!("{}", const_.display(db, edition)))
+                        .map(|const_| format_smolstr!("{}", const_.display(db, display_target)))
                 }
             })
     }
@@ -5345,7 +5378,7 @@ impl Type {
     pub fn generic_parameters<'a>(
         &'a self,
         db: &'a dyn HirDatabase,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> impl Iterator<Item = SmolStr> + 'a {
         // iterate the lifetime
         self.as_adt()
@@ -5355,7 +5388,7 @@ impl Type {
             })
             .into_iter()
             // add the type and const parameters
-            .chain(self.type_and_const_arguments(db, edition))
+            .chain(self.type_and_const_arguments(db, display_target))
     }
 
     pub fn iterate_method_candidates_with_traits<T>(
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 1b8531209c1..034e727d31b 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -313,6 +313,14 @@ impl<'db> SemanticsImpl<'db> {
         tree
     }
 
+    /// If not crate is found for the file, returns the last crate in topological order.
+    pub fn first_crate_or_default(&self, file: FileId) -> Crate {
+        match self.file_to_module_defs(file).next() {
+            Some(module) => module.krate(),
+            None => (*self.db.crate_graph().crates_in_topological_order().last().unwrap()).into(),
+        }
+    }
+
     pub fn attach_first_edition(&self, file: FileId) -> Option<EditionedFileId> {
         Some(EditionedFileId::new(
             file,
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index 2ebd88edae2..81eb6a70ad7 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -13,11 +13,10 @@ use hir_def::{
 use hir_expand::{name::Name, HirFileId};
 use hir_ty::{
     db::HirDatabase,
-    display::{hir_display_with_types_map, HirDisplay},
+    display::{hir_display_with_types_map, DisplayTarget, HirDisplay},
 };
 use intern::Symbol;
 use rustc_hash::FxHashMap;
-use span::Edition;
 use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr};
 
 use crate::{Module, ModuleDef, Semantics};
@@ -66,7 +65,7 @@ pub struct SymbolCollector<'a> {
     symbols: FxIndexSet<FileSymbol>,
     work: Vec<SymbolCollectorWork>,
     current_container_name: Option<SmolStr>,
-    edition: Edition,
+    display_target: DisplayTarget,
 }
 
 /// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect
@@ -78,7 +77,10 @@ impl<'a> SymbolCollector<'a> {
             symbols: Default::default(),
             work: Default::default(),
             current_container_name: None,
-            edition: Edition::Edition2015,
+            display_target: DisplayTarget::from_crate(
+                db,
+                *db.crate_graph().crates_in_topological_order().last().unwrap(),
+            ),
         }
     }
 
@@ -91,7 +93,7 @@ impl<'a> SymbolCollector<'a> {
     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);
+        self.display_target = module.krate().to_display_target(self.db);
 
         // The initial work is the root module we're collecting, additional work will
         // be populated as we traverse the module's definitions.
@@ -307,7 +309,7 @@ impl<'a> SymbolCollector<'a> {
         let impl_data = self.db.impl_data(impl_id);
         let impl_name = Some(
             hir_display_with_types_map(impl_data.self_ty, &impl_data.types_map)
-                .display(self.db, self.edition)
+                .display(self.db, self.display_target)
                 .to_smolstr(),
         );
         self.with_container_name(impl_name, |s| {
diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
index d2070f0e18b..0d672dc332f 100644
--- a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
@@ -4,7 +4,7 @@ use hir_def::ImportPathConfig;
 use hir_expand::mod_path::ModPath;
 use hir_ty::{
     db::HirDatabase,
-    display::{DisplaySourceCodeError, HirDisplay},
+    display::{DisplaySourceCodeError, DisplayTarget, HirDisplay},
 };
 use itertools::Itertools;
 use span::Edition;
@@ -99,14 +99,16 @@ impl Expr {
         sema_scope: &SemanticsScope<'_>,
         many_formatter: &mut dyn FnMut(&Type) -> String,
         cfg: ImportPathConfig,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> Result<String, DisplaySourceCodeError> {
         let db = sema_scope.db;
+        let edition = display_target.edition;
         let mod_item_path_str = |s, def| mod_item_path_str(s, def, cfg, edition);
         match self {
             Expr::Const(it) => match it.as_assoc_item(db).map(|it| it.container(db)) {
                 Some(container) => {
-                    let container_name = container_name(container, sema_scope, cfg, edition)?;
+                    let container_name =
+                        container_name(container, sema_scope, cfg, edition, display_target)?;
                     let const_name = it
                         .name(db)
                         .map(|c| c.display(db.upcast(), edition).to_string())
@@ -122,14 +124,15 @@ impl Expr {
             Expr::Function { func, params, .. } => {
                 let args = params
                     .iter()
-                    .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition))
+                    .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, display_target))
                     .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                     .into_iter()
                     .join(", ");
 
                 match func.as_assoc_item(db).map(|it| it.container(db)) {
                     Some(container) => {
-                        let container_name = container_name(container, sema_scope, cfg, edition)?;
+                        let container_name =
+                            container_name(container, sema_scope, cfg, edition, display_target)?;
                         let fn_name = func.name(db).display(db.upcast(), edition).to_string();
                         Ok(format!("{container_name}::{fn_name}({args})"))
                     }
@@ -147,10 +150,10 @@ impl Expr {
                 let func_name = func.name(db).display(db.upcast(), edition).to_string();
                 let self_param = func.self_param(db).unwrap();
                 let target_str =
-                    target.gen_source_code(sema_scope, many_formatter, cfg, edition)?;
+                    target.gen_source_code(sema_scope, many_formatter, cfg, display_target)?;
                 let args = params
                     .iter()
-                    .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition))
+                    .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, display_target))
                     .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                     .into_iter()
                     .join(", ");
@@ -180,7 +183,9 @@ impl Expr {
                     StructKind::Tuple => {
                         let args = params
                             .iter()
-                            .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg, edition))
+                            .map(|f| {
+                                f.gen_source_code(sema_scope, many_formatter, cfg, display_target)
+                            })
                             .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                             .into_iter()
                             .join(", ");
@@ -195,7 +200,12 @@ impl Expr {
                                 let tmp = format!(
                                     "{}: {}",
                                     f.name(db).display(db.upcast(), edition),
-                                    a.gen_source_code(sema_scope, many_formatter, cfg, edition)?
+                                    a.gen_source_code(
+                                        sema_scope,
+                                        many_formatter,
+                                        cfg,
+                                        display_target
+                                    )?
                                 );
                                 Ok(tmp)
                             })
@@ -215,7 +225,9 @@ impl Expr {
                     StructKind::Tuple => {
                         let args = params
                             .iter()
-                            .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, edition))
+                            .map(|a| {
+                                a.gen_source_code(sema_scope, many_formatter, cfg, display_target)
+                            })
                             .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                             .into_iter()
                             .join(", ");
@@ -230,7 +242,12 @@ impl Expr {
                                 let tmp = format!(
                                     "{}: {}",
                                     f.name(db).display(db.upcast(), edition),
-                                    a.gen_source_code(sema_scope, many_formatter, cfg, edition)?
+                                    a.gen_source_code(
+                                        sema_scope,
+                                        many_formatter,
+                                        cfg,
+                                        display_target
+                                    )?
                                 );
                                 Ok(tmp)
                             })
@@ -248,7 +265,7 @@ impl Expr {
             Expr::Tuple { params, .. } => {
                 let args = params
                     .iter()
-                    .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, edition))
+                    .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg, display_target))
                     .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                     .into_iter()
                     .join(", ");
@@ -260,7 +277,8 @@ impl Expr {
                     return Ok(many_formatter(&expr.ty(db)));
                 }
 
-                let strukt = expr.gen_source_code(sema_scope, many_formatter, cfg, edition)?;
+                let strukt =
+                    expr.gen_source_code(sema_scope, many_formatter, cfg, display_target)?;
                 let field = field.name(db).display(db.upcast(), edition).to_string();
                 Ok(format!("{strukt}.{field}"))
             }
@@ -269,7 +287,8 @@ impl Expr {
                     return Ok(many_formatter(&expr.ty(db)));
                 }
 
-                let inner = expr.gen_source_code(sema_scope, many_formatter, cfg, edition)?;
+                let inner =
+                    expr.gen_source_code(sema_scope, many_formatter, cfg, display_target)?;
                 Ok(format!("&{inner}"))
             }
             Expr::Many(ty) => Ok(many_formatter(ty)),
@@ -358,6 +377,7 @@ fn container_name(
     sema_scope: &SemanticsScope<'_>,
     cfg: ImportPathConfig,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Result<String, DisplaySourceCodeError> {
     let container_name = match container {
         crate::AssocItemContainer::Trait(trait_) => {
@@ -368,7 +388,7 @@ fn container_name(
             // Should it be guaranteed that `mod_item_path` always exists?
             match self_ty.as_adt().and_then(|adt| mod_item_path(sema_scope, &adt.into(), cfg)) {
                 Some(path) => path.display(sema_scope.db.upcast(), edition).to_string(),
-                None => self_ty.display(sema_scope.db, edition).to_string(),
+                None => self_ty.display(sema_scope.db, display_target).to_string(),
             }
         }
     };
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
index 91e248a1de5..7af2a2e1e6a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
@@ -724,9 +724,9 @@ fn fn_generic_params(
     filter_unnecessary_bounds(&mut generic_params, &mut where_preds, necessary_params);
     filter_bounds_in_scope(&mut generic_params, &mut where_preds, ctx, target);
 
-    let generic_params: Vec<_> =
+    let generic_params: Vec<ast::GenericParam> =
         generic_params.into_iter().map(|it| it.node.clone_for_update()).collect();
-    let where_preds: Vec<_> =
+    let where_preds: Vec<ast::WherePred> =
         where_preds.into_iter().map(|it| it.node.clone_for_update()).collect();
 
     // 4. Rewrite paths
@@ -1116,9 +1116,12 @@ fn fn_arg_type(
 
         if ty.is_reference() || ty.is_mutable_reference() {
             let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate());
-            let target_edition = target_module.krate().edition(ctx.db());
             convert_reference_type(ty.strip_references(), ctx.db(), famous_defs)
-                .map(|conversion| conversion.convert_type(ctx.db(), target_edition).to_string())
+                .map(|conversion| {
+                    conversion
+                        .convert_type(ctx.db(), target_module.krate().to_display_target(ctx.db()))
+                        .to_string()
+                })
                 .or_else(|| ty.display_source_code(ctx.db(), target_module.into(), true).ok())
         } else {
             ty.display_source_code(ctx.db(), target_module.into(), true).ok()
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
index ac58af62525..1b16ba5fc8f 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
@@ -233,7 +233,7 @@ fn generate_getter_from_info(
                 .map(|conversion| {
                     cov_mark::hit!(convert_reference_type);
                     (
-                        conversion.convert_type(ctx.db(), krate.edition(ctx.db())),
+                        conversion.convert_type(ctx.db(), krate.to_display_target(ctx.db())),
                         conversion.getter(record_field_info.field_name.to_string()),
                     )
                 })
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
index 139078eee7c..ca5882d0313 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
@@ -42,7 +42,7 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_>
         let value = konst
             .eval(ctx.sema.db)
             .ok()?
-            .render(ctx.sema.db, konst.krate(ctx.sema.db).edition(ctx.sema.db));
+            .render(ctx.sema.db, konst.krate(ctx.sema.db).to_display_target(ctx.sema.db));
 
         let id = AssistId("inline_const_as_literal", AssistKind::RefactorInline);
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
index 66671c934c4..e10897b3bef 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
@@ -52,8 +52,13 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
     let paths = paths
         .into_iter()
         .filter_map(|path| {
-            path.gen_source_code(&scope, &mut formatter, ctx.config.import_path_config(), edition)
-                .ok()
+            path.gen_source_code(
+                &scope,
+                &mut formatter,
+                ctx.config.import_path_config(),
+                scope.krate().to_display_target(ctx.db()),
+            )
+            .ok()
         })
         .unique();
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
index 39686f065a9..a6fa1706710 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -3,7 +3,8 @@
 pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
 use hir::{
     db::{ExpandDatabase, HirDatabase},
-    HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, Semantics,
+    DisplayTarget, HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution,
+    Semantics,
 };
 use ide_db::{
     famous_defs::FamousDefs,
@@ -21,7 +22,7 @@ use syntax::{
         syntax_factory::SyntaxFactory,
         HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace,
     },
-    ted, AstNode, AstToken, Direction, Edition, NodeOrToken, SourceFile,
+    ted, AstNode, AstToken, Direction, NodeOrToken, SourceFile,
     SyntaxKind::*,
     SyntaxNode, SyntaxToken, TextRange, TextSize, WalkEvent, T,
 };
@@ -793,31 +794,50 @@ enum ReferenceConversionType {
 }
 
 impl ReferenceConversion {
-    pub(crate) fn convert_type(&self, db: &dyn HirDatabase, edition: Edition) -> ast::Type {
+    pub(crate) fn convert_type(
+        &self,
+        db: &dyn HirDatabase,
+        display_target: DisplayTarget,
+    ) -> ast::Type {
         let ty = match self.conversion {
-            ReferenceConversionType::Copy => self.ty.display(db, edition).to_string(),
+            ReferenceConversionType::Copy => self.ty.display(db, display_target).to_string(),
             ReferenceConversionType::AsRefStr => "&str".to_owned(),
             ReferenceConversionType::AsRefSlice => {
-                let type_argument_name =
-                    self.ty.type_arguments().next().unwrap().display(db, edition).to_string();
+                let type_argument_name = self
+                    .ty
+                    .type_arguments()
+                    .next()
+                    .unwrap()
+                    .display(db, display_target)
+                    .to_string();
                 format!("&[{type_argument_name}]")
             }
             ReferenceConversionType::Dereferenced => {
-                let type_argument_name =
-                    self.ty.type_arguments().next().unwrap().display(db, edition).to_string();
+                let type_argument_name = self
+                    .ty
+                    .type_arguments()
+                    .next()
+                    .unwrap()
+                    .display(db, display_target)
+                    .to_string();
                 format!("&{type_argument_name}")
             }
             ReferenceConversionType::Option => {
-                let type_argument_name =
-                    self.ty.type_arguments().next().unwrap().display(db, edition).to_string();
+                let type_argument_name = self
+                    .ty
+                    .type_arguments()
+                    .next()
+                    .unwrap()
+                    .display(db, display_target)
+                    .to_string();
                 format!("Option<&{type_argument_name}>")
             }
             ReferenceConversionType::Result => {
                 let mut type_arguments = self.ty.type_arguments();
                 let first_type_argument_name =
-                    type_arguments.next().unwrap().display(db, edition).to_string();
+                    type_arguments.next().unwrap().display(db, display_target).to_string();
                 let second_type_argument_name =
-                    type_arguments.next().unwrap().display(db, edition).to_string();
+                    type_arguments.next().unwrap().display(db, display_target).to_string();
                 format!("Result<&{first_type_argument_name}, &{second_type_argument_name}>")
             }
         };
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 919b30f7f97..e686a293094 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -7,8 +7,8 @@ mod tests;
 use std::{iter, ops::ControlFlow};
 
 use hir::{
-    HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, Semantics,
-    SemanticsScope, Symbol, Type, TypeInfo,
+    DisplayTarget, HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution,
+    ScopeDef, Semantics, SemanticsScope, Symbol, Type, TypeInfo,
 };
 use ide_db::{
     base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition,
@@ -440,6 +440,7 @@ pub(crate) struct CompletionContext<'a> {
     pub(crate) token: SyntaxToken,
     /// The crate of the current file.
     pub(crate) krate: hir::Crate,
+    pub(crate) display_target: DisplayTarget,
     /// The module of the `scope`.
     pub(crate) module: hir::Module,
     /// The function where we're completing, if inside a function.
@@ -867,6 +868,7 @@ impl<'a> CompletionContext<'a> {
             CompleteSemicolon::DoNotComplete
         };
 
+        let display_target = krate.to_display_target(db);
         let ctx = CompletionContext {
             sema,
             scope,
@@ -888,6 +890,7 @@ impl<'a> CompletionContext<'a> {
             exclude_flyimport,
             exclude_traits,
             complete_semicolon,
+            display_target,
         };
         Some((ctx, analysis))
     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
index fc2bfc01e62..a03f632cdfd 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
@@ -13,7 +13,7 @@ fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str,
 
     let ty = completion_context
         .expected_type
-        .map(|t| t.display_test(&db).to_string())
+        .map(|t| t.display_test(&db, completion_context.krate.to_display_target(&db)).to_string())
         .unwrap_or("?".to_owned());
 
     let name =
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 4f6c4cb6639..b32a589a1b2 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -144,7 +144,7 @@ pub(crate) fn render_field(
         is_skipping_completion: receiver.is_some(),
         ..CompletionRelevance::default()
     });
-    item.detail(ty.display(db, ctx.completion.edition).to_string())
+    item.detail(ty.display(db, ctx.completion.display_target).to_string())
         .set_documentation(field.docs(db))
         .set_deprecated(is_deprecated)
         .lookup_by(name);
@@ -212,7 +212,7 @@ pub(crate) fn render_tuple_field(
         field_with_receiver(receiver.as_deref(), &field.to_string()),
         ctx.completion.edition,
     );
-    item.detail(ty.display(ctx.db(), ctx.completion.edition).to_string())
+    item.detail(ty.display(ctx.db(), ctx.completion.display_target).to_string())
         .lookup_by(field.to_string());
     item.set_relevance(CompletionRelevance {
         is_skipping_completion: receiver.is_some(),
@@ -303,7 +303,8 @@ pub(crate) fn render_expr(
 
     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()?;
+    let label =
+        expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.display_target).ok()?;
 
     let source_range = match ctx.original_token.parent() {
         Some(node) => match node.ancestors().find_map(ast::Path::cast) {
@@ -318,7 +319,7 @@ pub(crate) fn render_expr(
 
     let snippet = format!(
         "{}$0",
-        expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.edition).ok()?
+        expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg, ctx.display_target).ok()?
     );
     let edit = TextEdit::replace(source_range, snippet);
     item.snippet_edit(ctx.config.snippet_cap?, edit);
@@ -398,6 +399,8 @@ fn render_resolution_path(
     let _p = tracing::info_span!("render_resolution_path").entered();
     use hir::ModuleDef::*;
 
+    let krate = ctx.completion.display_target;
+
     match resolution {
         ScopeDef::ModuleDef(Macro(mac)) => {
             let ctx = ctx.import_to_add(import_to_add);
@@ -459,7 +462,7 @@ fn render_resolution_path(
 
     let mut set_item_relevance = |ty: Type| {
         if !ty.is_unknown() {
-            item.detail(ty.display(db, completion.edition).to_string());
+            item.detail(ty.display(db, krate).to_string());
         }
 
         item.set_relevance(CompletionRelevance {
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 e357ab24d22..f11b3023679 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
@@ -16,7 +16,7 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem>
     let name = const_.name(db)?;
     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 detail = const_.display(db, ctx.completion.display_target).to_string();
 
     let mut item =
         CompletionItem::new(SymbolKind::Const, ctx.source_range(), name, ctx.completion.edition);
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 fd90613964a..4693bdc047f 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
@@ -4,7 +4,7 @@ use hir::{db::HirDatabase, AsAssocItem, HirDisplay};
 use ide_db::{SnippetCap, SymbolKind};
 use itertools::Itertools;
 use stdx::{format_to, to_lower_snake_case};
-use syntax::{format_smolstr, AstNode, Edition, SmolStr, ToSmolStr};
+use syntax::{format_smolstr, AstNode, SmolStr, ToSmolStr};
 
 use crate::{
     context::{
@@ -142,9 +142,9 @@ fn render(
     }
 
     let detail = if ctx.completion.config.full_function_signatures {
-        detail_full(db, func, ctx.completion.edition)
+        detail_full(ctx.completion, func)
     } else {
-        detail(ctx.completion, func, ctx.completion.edition)
+        detail(ctx.completion, func)
     };
     item.set_documentation(ctx.docs(func))
         .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
@@ -251,7 +251,7 @@ pub(super) fn add_call_parens<'b>(
                     format!(
                         "{}(${{1:{}}}{}{})$0",
                         escaped_name,
-                        self_param.display(ctx.db, ctx.edition),
+                        self_param.display(ctx.db, ctx.display_target),
                         if params.is_empty() { "" } else { ", " },
                         function_params_snippet
                     )
@@ -307,7 +307,7 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta
     ""
 }
 
-fn detail(ctx: &CompletionContext<'_>, func: hir::Function, edition: Edition) -> String {
+fn detail(ctx: &CompletionContext<'_>, func: hir::Function) -> String {
     let mut ret_ty = func.ret_type(ctx.db);
     let mut detail = String::new();
 
@@ -324,15 +324,15 @@ fn detail(ctx: &CompletionContext<'_>, func: hir::Function, edition: Edition) ->
         format_to!(detail, "unsafe ");
     }
 
-    format_to!(detail, "fn({})", params_display(ctx.db, func, edition));
+    format_to!(detail, "fn({})", params_display(ctx, func));
     if !ret_ty.is_unit() {
-        format_to!(detail, " -> {}", ret_ty.display(ctx.db, edition));
+        format_to!(detail, " -> {}", ret_ty.display(ctx.db, ctx.display_target));
     }
     detail
 }
 
-fn detail_full(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> String {
-    let signature = format!("{}", func.display(db, edition));
+fn detail_full(ctx: &CompletionContext<'_>, func: hir::Function) -> String {
+    let signature = format!("{}", func.display(ctx.db, ctx.display_target));
     let mut detail = String::with_capacity(signature.len());
 
     for segment in signature.split_whitespace() {
@@ -346,24 +346,24 @@ fn detail_full(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> S
     detail
 }
 
-fn params_display(db: &dyn HirDatabase, func: hir::Function, edition: Edition) -> String {
-    if let Some(self_param) = func.self_param(db) {
-        let assoc_fn_params = func.assoc_fn_params(db);
+fn params_display(ctx: &CompletionContext<'_>, func: hir::Function) -> String {
+    if let Some(self_param) = func.self_param(ctx.db) {
+        let assoc_fn_params = func.assoc_fn_params(ctx.db);
         let params = assoc_fn_params
             .iter()
             .skip(1) // skip the self param because we are manually handling that
-            .map(|p| p.ty().display(db, edition));
+            .map(|p| p.ty().display(ctx.db, ctx.display_target));
         format!(
             "{}{}",
-            self_param.display(db, edition),
+            self_param.display(ctx.db, ctx.display_target),
             params.format_with("", |display, f| {
                 f(&", ")?;
                 f(&display)
             })
         )
     } else {
-        let assoc_fn_params = func.assoc_fn_params(db);
-        assoc_fn_params.iter().map(|p| p.ty().display(db, edition)).join(", ")
+        let assoc_fn_params = func.assoc_fn_params(ctx.db);
+        assoc_fn_params.iter().map(|p| p.ty().display(ctx.db, ctx.display_target)).join(", ")
     }
 }
 
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 aab54ca5e01..3429ae1f46d 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
@@ -82,10 +82,10 @@ fn render(
 
     let mut rendered = match kind {
         StructKind::Tuple if should_add_parens => {
-            render_tuple_lit(db, snippet_cap, &fields, &escaped_qualified_name, completion.edition)
+            render_tuple_lit(completion, snippet_cap, &fields, &escaped_qualified_name)
         }
         StructKind::Record if should_add_parens => {
-            render_record_lit(db, snippet_cap, &fields, &escaped_qualified_name, completion.edition)
+            render_record_lit(completion, snippet_cap, &fields, &escaped_qualified_name)
         }
         _ => RenderedLiteral {
             literal: escaped_qualified_name.clone(),
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 e265e92f979..8b2476d153f 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
@@ -62,7 +62,7 @@ fn render(
         completion.edition,
     );
     item.set_deprecated(ctx.is_deprecated(macro_))
-        .detail(macro_.display(completion.db, completion.edition).to_string())
+        .detail(macro_.display(completion.db, completion.display_target).to_string())
         .set_documentation(docs)
         .set_relevance(ctx.completion_relevance());
 
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 1b952f31360..d57feee4fa6 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
@@ -38,7 +38,7 @@ fn render(
     } else {
         (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();
+    let detail = type_alias.display(db, ctx.completion.display_target).to_string();
 
     let mut item = CompletionItem::new(
         SymbolKind::TypeAlias,
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 74203626521..09154e81c03 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
@@ -88,7 +88,7 @@ pub(crate) fn render_union_literal(
             f(&format_args!(
                 "{}: {}",
                 field.name(ctx.db()).display(ctx.db(), ctx.completion.edition),
-                field.ty(ctx.db()).display(ctx.db(), ctx.completion.edition)
+                field.ty(ctx.db()).display(ctx.db(), ctx.completion.display_target)
             ))
         }),
         if fields_omitted { ", .." } else { "" }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs
index d8516ea1078..83718e57229 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/variant.rs
@@ -1,10 +1,10 @@
 //! Code common to structs, unions, and enum variants.
 
 use crate::context::CompletionContext;
-use hir::{db::HirDatabase, sym, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind};
+use hir::{sym, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind};
 use ide_db::SnippetCap;
 use itertools::Itertools;
-use syntax::{Edition, SmolStr};
+use syntax::SmolStr;
 
 /// A rendered struct, union, or enum variant, split into fields for actual
 /// auto-completion (`literal`, using `field: ()`) and display in the
@@ -17,11 +17,10 @@ pub(crate) struct RenderedLiteral {
 /// Render a record type (or sub-type) to a `RenderedCompound`. Use `None` for
 /// the `name` argument for an anonymous type.
 pub(crate) fn render_record_lit(
-    db: &dyn HirDatabase,
+    ctx: &CompletionContext<'_>,
     snippet_cap: Option<SnippetCap>,
     fields: &[hir::Field],
     path: &str,
-    edition: Edition,
 ) -> RenderedLiteral {
     if snippet_cap.is_none() {
         return RenderedLiteral { literal: path.to_owned(), detail: path.to_owned() };
@@ -30,19 +29,19 @@ pub(crate) fn render_record_lit(
         if snippet_cap.is_some() {
             f(&format_args!(
                 "{}: ${{{}:()}}",
-                field.name(db).display(db.upcast(), edition),
+                field.name(ctx.db).display(ctx.db, ctx.edition),
                 idx + 1
             ))
         } else {
-            f(&format_args!("{}: ()", field.name(db).display(db.upcast(), edition)))
+            f(&format_args!("{}: ()", field.name(ctx.db).display(ctx.db, ctx.edition)))
         }
     });
 
     let types = fields.iter().format_with(", ", |field, f| {
         f(&format_args!(
             "{}: {}",
-            field.name(db).display(db.upcast(), edition),
-            field.ty(db).display(db, edition)
+            field.name(ctx.db).display(ctx.db, ctx.edition),
+            field.ty(ctx.db).display(ctx.db, ctx.display_target)
         ))
     });
 
@@ -55,11 +54,10 @@ pub(crate) fn render_record_lit(
 /// Render a tuple type (or sub-type) to a `RenderedCompound`. Use `None` for
 /// the `name` argument for an anonymous type.
 pub(crate) fn render_tuple_lit(
-    db: &dyn HirDatabase,
+    ctx: &CompletionContext<'_>,
     snippet_cap: Option<SnippetCap>,
     fields: &[hir::Field],
     path: &str,
-    edition: Edition,
 ) -> RenderedLiteral {
     if snippet_cap.is_none() {
         return RenderedLiteral { literal: path.to_owned(), detail: path.to_owned() };
@@ -72,7 +70,9 @@ pub(crate) fn render_tuple_lit(
         }
     });
 
-    let types = fields.iter().format_with(", ", |field, f| f(&field.ty(db).display(db, edition)));
+    let types = fields
+        .iter()
+        .format_with(", ", |field, f| f(&field.ty(ctx.db).display(ctx.db, ctx.display_target)));
 
     RenderedLiteral {
         literal: format!("{path}({completions})"),
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 6f71c3d9bd7..502314ed1e0 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -12,11 +12,11 @@ use arrayvec::ArrayVec;
 use either::Either;
 use hir::{
     Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
-    Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field,
-    Function, GenericDef, GenericParam, GenericSubstitution, HasContainer, HasVisibility,
-    HirDisplay, Impl, InlineAsmOperand, ItemContainer, Label, Local, Macro, Module, ModuleDef,
-    Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule, Trait, TraitAlias,
-    TupleField, TypeAlias, Variant, VariantDef, Visibility,
+    Const, Crate, DefWithBody, DeriveHelper, DisplayTarget, DocLinkDef, ExternAssocItem,
+    ExternCrateDecl, Field, Function, GenericDef, GenericParam, GenericSubstitution, HasContainer,
+    HasVisibility, HirDisplay, Impl, InlineAsmOperand, ItemContainer, Label, Local, Macro, Module,
+    ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule, Trait,
+    TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
 };
 use span::Edition;
 use stdx::{format_to, impl_from};
@@ -207,7 +207,7 @@ impl Definition {
         &self,
         db: &RootDatabase,
         famous_defs: Option<&FamousDefs<'_, '_>>,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> Option<Documentation> {
         let docs = match self {
             Definition::Macro(it) => it.docs(db),
@@ -228,7 +228,7 @@ impl Definition {
                     let docs = adt.docs(db)?;
                     let docs = format!(
                         "*This is the documentation for* `{}`\n\n{}",
-                        adt.display(db, edition),
+                        adt.display(db, display_target),
                         docs.as_str()
                     );
                     Some(Documentation::new(docs))
@@ -237,8 +237,9 @@ impl Definition {
             Definition::BuiltinType(it) => {
                 famous_defs.and_then(|fd| {
                     // std exposes prim_{} modules with docstrings on the root to document the builtins
-                    let primitive_mod = format!("prim_{}", it.name().display(fd.0.db, edition));
-                    let doc_owner = find_std_module(fd, &primitive_mod, edition)?;
+                    let primitive_mod =
+                        format!("prim_{}", it.name().display(fd.0.db, display_target.edition));
+                    let doc_owner = find_std_module(fd, &primitive_mod, display_target.edition)?;
                     doc_owner.docs(fd.0.db)
                 })
             }
@@ -256,16 +257,21 @@ impl Definition {
                 let AttributeTemplate { word, list, name_value_str } = it.template(db)?;
                 let mut docs = "Valid forms are:".to_owned();
                 if word {
-                    format_to!(docs, "\n - #\\[{}]", name.display(db, edition));
+                    format_to!(docs, "\n - #\\[{}]", name.display(db, display_target.edition));
                 }
                 if let Some(list) = list {
-                    format_to!(docs, "\n - #\\[{}({})]", name.display(db, edition), list);
+                    format_to!(
+                        docs,
+                        "\n - #\\[{}({})]",
+                        name.display(db, display_target.edition),
+                        list
+                    );
                 }
                 if let Some(name_value_str) = name_value_str {
                     format_to!(
                         docs,
                         "\n - #\\[{} = {}]",
-                        name.display(db, edition),
+                        name.display(db, display_target.edition),
                         name_value_str
                     );
                 }
@@ -288,49 +294,60 @@ impl Definition {
         })
     }
 
-    pub fn label(&self, db: &RootDatabase, edition: Edition) -> String {
+    pub fn label(&self, db: &RootDatabase, display_target: DisplayTarget) -> String {
         match *self {
-            Definition::Macro(it) => it.display(db, edition).to_string(),
-            Definition::Field(it) => it.display(db, edition).to_string(),
-            Definition::TupleField(it) => it.display(db, edition).to_string(),
-            Definition::Module(it) => it.display(db, edition).to_string(),
-            Definition::Crate(it) => it.display(db, edition).to_string(),
-            Definition::Function(it) => it.display(db, edition).to_string(),
-            Definition::Adt(it) => it.display(db, edition).to_string(),
-            Definition::Variant(it) => it.display(db, edition).to_string(),
-            Definition::Const(it) => it.display(db, edition).to_string(),
-            Definition::Static(it) => it.display(db, edition).to_string(),
-            Definition::Trait(it) => it.display(db, edition).to_string(),
-            Definition::TraitAlias(it) => it.display(db, edition).to_string(),
-            Definition::TypeAlias(it) => it.display(db, edition).to_string(),
-            Definition::BuiltinType(it) => it.name().display(db, edition).to_string(),
-            Definition::BuiltinLifetime(it) => it.name().display(db, edition).to_string(),
+            Definition::Macro(it) => it.display(db, display_target).to_string(),
+            Definition::Field(it) => it.display(db, display_target).to_string(),
+            Definition::TupleField(it) => it.display(db, display_target).to_string(),
+            Definition::Module(it) => it.display(db, display_target).to_string(),
+            Definition::Crate(it) => it.display(db, display_target).to_string(),
+            Definition::Function(it) => it.display(db, display_target).to_string(),
+            Definition::Adt(it) => it.display(db, display_target).to_string(),
+            Definition::Variant(it) => it.display(db, display_target).to_string(),
+            Definition::Const(it) => it.display(db, display_target).to_string(),
+            Definition::Static(it) => it.display(db, display_target).to_string(),
+            Definition::Trait(it) => it.display(db, display_target).to_string(),
+            Definition::TraitAlias(it) => it.display(db, display_target).to_string(),
+            Definition::TypeAlias(it) => it.display(db, display_target).to_string(),
+            Definition::BuiltinType(it) => {
+                it.name().display(db, display_target.edition).to_string()
+            }
+            Definition::BuiltinLifetime(it) => {
+                it.name().display(db, display_target.edition).to_string()
+            }
             Definition::Local(it) => {
                 let ty = it.ty(db);
-                let ty_display = ty.display_truncated(db, None, edition);
+                let ty_display = ty.display_truncated(db, None, display_target);
                 let is_mut = if it.is_mut(db) { "mut " } else { "" };
                 if it.is_self(db) {
                     format!("{is_mut}self: {ty_display}")
                 } else {
                     let name = it.name(db);
                     let let_kw = if it.is_param(db) { "" } else { "let " };
-                    format!("{let_kw}{is_mut}{}: {ty_display}", name.display(db, edition))
+                    format!(
+                        "{let_kw}{is_mut}{}: {ty_display}",
+                        name.display(db, display_target.edition)
+                    )
                 }
             }
             Definition::SelfType(impl_def) => {
                 let self_ty = &impl_def.self_ty(db);
                 match self_ty.as_adt() {
-                    Some(it) => it.display(db, edition).to_string(),
-                    None => self_ty.display(db, edition).to_string(),
+                    Some(it) => it.display(db, display_target).to_string(),
+                    None => self_ty.display(db, display_target).to_string(),
                 }
             }
-            Definition::GenericParam(it) => it.display(db, edition).to_string(),
-            Definition::Label(it) => it.name(db).display(db, edition).to_string(),
-            Definition::ExternCrateDecl(it) => it.display(db, edition).to_string(),
-            Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db).display(db, edition)),
-            Definition::ToolModule(it) => it.name(db).display(db, edition).to_string(),
+            Definition::GenericParam(it) => it.display(db, display_target).to_string(),
+            Definition::Label(it) => it.name(db).display(db, display_target.edition).to_string(),
+            Definition::ExternCrateDecl(it) => it.display(db, display_target).to_string(),
+            Definition::BuiltinAttr(it) => {
+                format!("#[{}]", it.name(db).display(db, display_target.edition))
+            }
+            Definition::ToolModule(it) => {
+                it.name(db).display(db, display_target.edition).to_string()
+            }
             Definition::DeriveHelper(it) => {
-                format!("derive_helper {}", it.name(db).display(db, edition))
+                format!("derive_helper {}", it.name(db).display(db, display_target.edition))
             }
             // FIXME
             Definition::InlineAsmRegOrRegClass(_) => "inline_asm_reg_or_reg_class".to_owned(),
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 126b30470b7..a348a4ef7d3 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
@@ -192,7 +192,9 @@ impl<'a> PathTransform<'a> {
                     }
                 }
                 (Either::Left(k), None) => {
-                    if let Some(default) = k.default(db, target_edition) {
+                    if let Some(default) =
+                        k.default(db, target_module.krate().to_display_target(db))
+                    {
                         if let Some(default) = default.expr() {
                             const_substs.insert(k, default.syntax().clone_for_update());
                             defaulted_params.push(Either::Right(k));
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
index e3a1e12e029..af25c2b2e33 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
@@ -12,7 +12,7 @@ pub(crate) fn expected_function(
     Diagnostic::new_with_syntax_node_ptr(
         ctx,
         DiagnosticCode::RustcHardError("E0618"),
-        format!("expected function, found {}", d.found.display(ctx.sema.db, ctx.edition)),
+        format!("expected function, found {}", d.found.display(ctx.sema.db, ctx.display_target)),
         d.call.map(|it| it.into()),
     )
     .experimental()
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
index 5730508436d..82cd1f2fde6 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
@@ -8,7 +8,7 @@ macro_rules! format_ty {
             $fmt,
             $(
                 $arg
-                    .display($ctx.sema.db, $ctx.edition)
+                    .display($ctx.sema.db, $ctx.display_target)
                     .with_closure_style(ClosureStyle::ClosureWithId)
             ),*
         )
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
index a9ff06fb0ab..7d0f10983d7 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
@@ -8,7 +8,7 @@ pub(crate) fn moved_out_of_ref(ctx: &DiagnosticsContext<'_>, d: &hir::MovedOutOf
     Diagnostic::new_with_syntax_node_ptr(
         ctx,
         DiagnosticCode::RustcHardError("E0507"),
-        format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db, ctx.edition)),
+        format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db, ctx.display_target)),
         d.span,
     )
     .experimental() // spans are broken, and I'm not sure how precise we can detect copy types
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
index 1363a8ff0dd..3db2e013a39 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -30,7 +30,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
             (
                 format!("`fn {redundant_assoc_item_name}`"),
                 function.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
-                format!("\n    {};", function.display(db, ctx.edition)),
+                format!("\n    {};", function.display(db, ctx.display_target)),
             )
         }
         hir::AssocItem::Const(id) => {
@@ -38,7 +38,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
             (
                 format!("`const {redundant_assoc_item_name}`"),
                 constant.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
-                format!("\n    {};", constant.display(db, ctx.edition)),
+                format!("\n    {};", constant.display(db, ctx.display_target)),
             )
         }
         hir::AssocItem::TypeAlias(id) => {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 7cf8282d052..c726a3bcd3c 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -45,10 +45,10 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch)
         format!(
             "expected {}, found {}",
             d.expected
-                .display(ctx.sema.db, ctx.edition)
+                .display(ctx.sema.db, ctx.display_target)
                 .with_closure_style(ClosureStyle::ClosureWithId),
             d.actual
-                .display(ctx.sema.db, ctx.edition)
+                .display(ctx.sema.db, ctx.display_target)
                 .with_closure_style(ClosureStyle::ClosureWithId),
         ),
         display_range,
@@ -306,8 +306,8 @@ fn str_ref_to_owned(
     expr_ptr: &InFile<AstPtr<ast::Expr>>,
     acc: &mut Vec<Assist>,
 ) -> Option<()> {
-    let expected = d.expected.display(ctx.sema.db, ctx.edition);
-    let actual = d.actual.display(ctx.sema.db, ctx.edition);
+    let expected = d.expected.display(ctx.sema.db, ctx.display_target);
+    let actual = d.actual.display(ctx.sema.db, ctx.display_target);
 
     // FIXME do this properly
     if expected.to_string() != "String" || actual.to_string() != "&str" {
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 b023a95fb35..c25318eda48 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
@@ -27,7 +27,7 @@ pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Di
             format!(
                 "invalid `_` expression, expected type `{}`",
                 d.expected
-                    .display(ctx.sema.db, ctx.edition)
+                    .display(ctx.sema.db, ctx.display_target)
                     .with_closure_style(ClosureStyle::ClosureWithId),
             ),
             fixes(ctx, d),
@@ -72,7 +72,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
                     prefer_absolute: ctx.config.prefer_absolute,
                     allow_unstable: ctx.is_nightly,
                 },
-                ctx.edition,
+                ctx.display_target,
             )
             .ok()
         })
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
index dfb03eee732..6ab713a5896 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
@@ -38,7 +38,7 @@ pub(crate) fn unresolved_field(
         format!(
             "no field `{}` on type `{}`{method_suffix}",
             d.name.display(ctx.sema.db, ctx.edition),
-            d.receiver.display(ctx.sema.db, ctx.edition)
+            d.receiver.display(ctx.sema.db, ctx.display_target)
         ),
         adjusted_display_range(ctx, d.expr, &|expr| {
             Some(
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index e4de107249b..35e7521af70 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
@@ -31,7 +31,7 @@ pub(crate) fn unresolved_method(
         format!(
             "no method `{}` on type `{}`{suffix}",
             d.name.display(ctx.sema.db, ctx.edition),
-            d.receiver.display(ctx.sema.db, ctx.edition)
+            d.receiver.display(ctx.sema.db, ctx.display_target)
         ),
         adjusted_display_range(ctx, d.expr, &|expr| {
             Some(
@@ -152,7 +152,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
             receiver_type.as_adt()?.name(db).display_no_db(ctx.edition).to_smolstr();
 
         let generic_parameters: Vec<SmolStr> =
-            receiver_type.generic_parameters(db, ctx.edition).collect();
+            receiver_type.generic_parameters(db, ctx.display_target).collect();
         // if receiver should be pass as first arg in the assoc func,
         // we could omit generic parameters cause compiler can deduce it automatically
         if !need_to_take_receiver_as_first_arg && !generic_parameters.is_empty() {
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 0a55b6e9bee..e15d3495789 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -81,7 +81,10 @@ mod tests;
 use std::{collections::hash_map, iter, sync::LazyLock};
 
 use either::Either;
-use hir::{db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, HirFileId, InFile, Semantics};
+use hir::{
+    db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, DisplayTarget, HirFileId, InFile,
+    Semantics,
+};
 use ide_db::{
     assists::{Assist, AssistId, AssistKind, AssistResolveStrategy},
     base_db::{ReleaseChannel, SourceDatabase},
@@ -277,6 +280,7 @@ struct DiagnosticsContext<'a> {
     sema: Semantics<'a, RootDatabase>,
     resolve: &'a AssistResolveStrategy,
     edition: Edition,
+    display_target: DisplayTarget,
     is_nightly: bool,
 }
 
@@ -374,7 +378,18 @@ pub fn semantic_diagnostics(
         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 krate = module.map(|module| module.krate()).unwrap_or_else(|| {
+        (*db.crate_graph().crates_in_topological_order().last().unwrap()).into()
+    });
+    let display_target = krate.to_display_target(db);
+    let ctx = DiagnosticsContext {
+        config,
+        sema,
+        resolve,
+        edition: file_id.edition(),
+        is_nightly,
+        display_target,
+    };
 
     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 4bead14e31d..e219ba4bf63 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -7,8 +7,7 @@ use crate::{
     SsrMatches,
 };
 use hir::{FileRange, ImportPathConfig, Semantics};
-use ide_db::FxHashMap;
-use parser::Edition;
+use ide_db::{base_db::SourceDatabase, FxHashMap};
 use std::{cell::Cell, iter::Peekable};
 use syntax::{
     ast::{self, AstNode, AstToken, HasGenericArgs},
@@ -627,22 +626,23 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
                 match_error!("Failed to get receiver type for `{}`", expr.syntax().text())
             })?
             .original;
-        let edition = self
-            .sema
-            .scope(expr.syntax())
-            .map(|it| it.krate().edition(self.sema.db))
-            .unwrap_or(Edition::CURRENT);
-        // Temporary needed to make the borrow checker happy.
+        let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| {
+            hir::Crate::from(
+                *self.sema.db.crate_graph().crates_in_topological_order().last().unwrap(),
+            )
+        });
         let res = code_type
             .autoderef(self.sema.db)
             .enumerate()
             .find(|(_, deref_code_type)| pattern_type == deref_code_type)
             .map(|(count, _)| count)
             .ok_or_else(|| {
+                let display_target = krate.to_display_target(self.sema.db);
+                // Temporary needed to make the borrow checker happy.
                 match_error!(
                     "Pattern type `{}` didn't match code type `{}`",
-                    pattern_type.display(self.sema.db, edition),
-                    code_type.display(self.sema.db, edition)
+                    pattern_type.display(self.sema.db, display_target),
+                    code_type.display(self.sema.db, display_target)
                 )
             });
         res
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 9a3e77f3a93..b00de6ba408 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -7,7 +7,8 @@ use std::{iter, ops::Not};
 
 use either::Either;
 use hir::{
-    db::DefDatabase, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics,
+    db::DefDatabase, DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem,
+    Semantics,
 };
 use ide_db::{
     defs::{Definition, IdentClass, NameRefClass, OperatorClass},
@@ -129,10 +130,18 @@ pub(crate) fn hover(
     let file = sema.parse_guess_edition(file_id).syntax().clone();
     let edition =
         sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
+    let display_target = sema.first_crate_or_default(file_id).to_display_target(db);
     let mut res = if range.is_empty() {
-        hover_offset(sema, FilePosition { file_id, offset: range.start() }, file, config, edition)
+        hover_offset(
+            sema,
+            FilePosition { file_id, offset: range.start() },
+            file,
+            config,
+            edition,
+            display_target,
+        )
     } else {
-        hover_ranged(sema, frange, file, config, edition)
+        hover_ranged(sema, frange, file, config, edition, display_target)
     }?;
 
     if let HoverDocFormat::PlainText = config.format {
@@ -148,6 +157,7 @@ fn hover_offset(
     file: SyntaxNode,
     config: &HoverConfig,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<RangeInfo<HoverResult>> {
     let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
         IDENT
@@ -169,8 +179,18 @@ fn hover_offset(
     if let Some(doc_comment) = token_as_doc_comment(&original_token) {
         cov_mark::hit!(no_highlight_on_comment_hover);
         return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
-            let res =
-                hover_for_definition(sema, file_id, def, None, &node, None, false, config, edition);
+            let res = hover_for_definition(
+                sema,
+                file_id,
+                def,
+                None,
+                &node,
+                None,
+                false,
+                config,
+                edition,
+                display_target,
+            );
             Some(RangeInfo::new(range, res))
         });
     }
@@ -188,6 +208,7 @@ fn hover_offset(
             false,
             config,
             edition,
+            display_target,
         );
         return Some(RangeInfo::new(range, res));
     }
@@ -277,6 +298,7 @@ fn hover_offset(
                         hovered_definition,
                         config,
                         edition,
+                        display_target,
                     )
                 })
                 .collect::<Vec<_>>(),
@@ -286,12 +308,12 @@ fn hover_offset(
             res.extend(definitions);
             continue;
         }
-        let keywords = || render::keyword(sema, config, &token, edition);
+        let keywords = || render::keyword(sema, config, &token, edition, display_target);
         let underscore = || {
             if !is_same_kind {
                 return None;
             }
-            render::underscore(sema, config, &token, edition)
+            render::underscore(sema, config, &token, edition, display_target)
         };
         let rest_pat = || {
             if !is_same_kind || token.kind() != DOT2 {
@@ -305,7 +327,7 @@ fn hover_offset(
             let record_pat =
                 record_pat_field_list.syntax().parent().and_then(ast::RecordPat::cast)?;
 
-            Some(render::struct_rest_pat(sema, config, &record_pat, edition))
+            Some(render::struct_rest_pat(sema, config, &record_pat, edition, display_target))
         };
         let call = || {
             if !is_same_kind || token.kind() != T!['('] && token.kind() != T![')'] {
@@ -319,17 +341,17 @@ fn hover_offset(
                     _ => return None,
                 }
             };
-            render::type_info_of(sema, config, &Either::Left(call_expr), edition)
+            render::type_info_of(sema, config, &Either::Left(call_expr), edition, display_target)
         };
         let closure = || {
             if !is_same_kind || token.kind() != T![|] {
                 return None;
             }
             let c = token.parent().and_then(|x| x.parent()).and_then(ast::ClosureExpr::cast)?;
-            render::closure_expr(sema, config, c, edition)
+            render::closure_expr(sema, config, c, edition, display_target)
         };
         let literal = || {
-            render::literal(sema, original_token.clone(), edition)
+            render::literal(sema, original_token.clone(), display_target)
                 .map(|markup| HoverResult { markup, actions: vec![] })
         };
         if let Some(result) = keywords()
@@ -362,6 +384,7 @@ fn hover_ranged(
     file: SyntaxNode,
     config: &HoverConfig,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<RangeInfo<HoverResult>> {
     // FIXME: make this work in attributes
     let expr_or_pat = file
@@ -371,16 +394,17 @@ fn hover_ranged(
         .find_map(Either::<ast::Expr, ast::Pat>::cast)?;
     let res = match &expr_or_pat {
         Either::Left(ast::Expr::TryExpr(try_expr)) => {
-            render::try_expr(sema, config, try_expr, edition)
+            render::try_expr(sema, config, try_expr, edition, display_target)
         }
         Either::Left(ast::Expr::PrefixExpr(prefix_expr))
             if prefix_expr.op_kind() == Some(ast::UnaryOp::Deref) =>
         {
-            render::deref_expr(sema, config, prefix_expr, edition)
+            render::deref_expr(sema, config, prefix_expr, edition, display_target)
         }
         _ => None,
     };
-    let res = res.or_else(|| render::type_info_of(sema, config, &expr_or_pat, edition));
+    let res =
+        res.or_else(|| render::type_info_of(sema, config, &expr_or_pat, edition, display_target));
     res.map(|it| {
         let range = match expr_or_pat {
             Either::Left(it) => it.syntax().text_range(),
@@ -401,6 +425,7 @@ pub(crate) fn hover_for_definition(
     hovered_definition: bool,
     config: &HoverConfig,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> HoverResult {
     let famous_defs = match &def {
         Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())),
@@ -435,6 +460,7 @@ pub(crate) fn hover_for_definition(
         subst_types.as_ref(),
         config,
         edition,
+        display_target,
     );
     HoverResult {
         markup: render::process_markup(sema.db, def, &markup, config),
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 c5a83e58cea..31ef89a07cd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -3,7 +3,7 @@ use std::{env, mem, ops::Not};
 
 use either::Either;
 use hir::{
-    db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DropGlue,
+    db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DisplayTarget, DropGlue,
     DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError,
     MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
 };
@@ -38,12 +38,13 @@ pub(super) fn type_info_of(
     _config: &HoverConfig,
     expr_or_pat: &Either<ast::Expr, ast::Pat>,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
     let ty_info = match expr_or_pat {
         Either::Left(expr) => sema.type_of_expr(expr)?,
         Either::Right(pat) => sema.type_of_pat(pat)?,
     };
-    type_info(sema, _config, ty_info, edition)
+    type_info(sema, _config, ty_info, edition, display_target)
 }
 
 pub(super) fn closure_expr(
@@ -51,9 +52,10 @@ pub(super) fn closure_expr(
     config: &HoverConfig,
     c: ast::ClosureExpr,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
     let TypeInfo { original, .. } = sema.type_of_expr(&c.into())?;
-    closure_ty(sema, config, &TypeInfo { original, adjusted: None }, edition)
+    closure_ty(sema, config, &TypeInfo { original, adjusted: None }, edition, display_target)
 }
 
 pub(super) fn try_expr(
@@ -61,6 +63,7 @@ pub(super) fn try_expr(
     _config: &HoverConfig,
     try_expr: &ast::TryExpr,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
     let inner_ty = sema.type_of_expr(&try_expr.expr()?)?.original;
     let mut ancestors = try_expr.syntax().ancestors();
@@ -127,8 +130,8 @@ pub(super) fn try_expr(
         res.actions.push(actions);
     }
 
-    let inner_ty = inner_ty.display(sema.db, edition).to_string();
-    let body_ty = body_ty.display(sema.db, edition).to_string();
+    let inner_ty = inner_ty.display(sema.db, display_target).to_string();
+    let body_ty = body_ty.display(sema.db, display_target).to_string();
     let ty_len_max = inner_ty.len().max(body_ty.len());
 
     let l = "Propagated as: ".len() - " Type: ".len();
@@ -153,6 +156,7 @@ pub(super) fn deref_expr(
     _config: &HoverConfig,
     deref_expr: &ast::PrefixExpr,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
     let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original;
     let TypeInfo { original, adjusted } =
@@ -170,9 +174,9 @@ pub(super) fn deref_expr(
 
     res.markup = if let Some(adjusted_ty) = adjusted {
         walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def);
-        let original = original.display(sema.db, edition).to_string();
-        let adjusted = adjusted_ty.display(sema.db, edition).to_string();
-        let inner = inner_ty.display(sema.db, edition).to_string();
+        let original = original.display(sema.db, display_target).to_string();
+        let adjusted = adjusted_ty.display(sema.db, display_target).to_string();
+        let inner = inner_ty.display(sema.db, display_target).to_string();
         let type_len = "To type: ".len();
         let coerced_len = "Coerced to: ".len();
         let deref_len = "Dereferenced from: ".len();
@@ -190,8 +194,8 @@ pub(super) fn deref_expr(
         )
         .into()
     } else {
-        let original = original.display(sema.db, edition).to_string();
-        let inner = inner_ty.display(sema.db, edition).to_string();
+        let original = original.display(sema.db, display_target).to_string();
+        let inner = inner_ty.display(sema.db, display_target).to_string();
         let type_len = "To type: ".len();
         let deref_len = "Dereferenced from: ".len();
         let max_len = (original.len() + type_len).max(inner.len() + deref_len);
@@ -216,6 +220,7 @@ pub(super) fn underscore(
     config: &HoverConfig,
     token: &SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
     if token.kind() != T![_] {
         return None;
@@ -224,8 +229,8 @@ pub(super) fn underscore(
     let _it = match_ast! {
         match parent {
             ast::InferType(it) => it,
-            ast::UnderscoreExpr(it) => return type_info_of(sema, config, &Either::Left(ast::Expr::UnderscoreExpr(it)),edition),
-            ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(it)),edition),
+            ast::UnderscoreExpr(it) => return type_info_of(sema, config, &Either::Left(ast::Expr::UnderscoreExpr(it)),edition, display_target),
+            ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(it)),edition, display_target),
             _ => return None,
         }
     };
@@ -259,6 +264,7 @@ pub(super) fn keyword(
     config: &HoverConfig,
     token: &SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
     if !token.kind().is_keyword(edition) || !config.documentation || !config.keywords {
         return None;
@@ -267,7 +273,7 @@ pub(super) fn keyword(
     let famous_defs = FamousDefs(sema, sema.scope(&parent)?.krate());
 
     let KeywordHint { description, keyword_mod, actions } =
-        keyword_hints(sema, token, parent, edition);
+        keyword_hints(sema, token, parent, edition, display_target);
 
     let doc_owner = find_std_module(&famous_defs, &keyword_mod, edition)?;
     let docs = doc_owner.docs(sema.db)?;
@@ -288,6 +294,7 @@ pub(super) fn struct_rest_pat(
     _config: &HoverConfig,
     pattern: &ast::RecordPat,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> HoverResult {
     let missing_fields = sema.record_pattern_missing_fields(pattern);
 
@@ -309,7 +316,7 @@ pub(super) fn struct_rest_pat(
     res.markup = {
         let mut s = String::from(".., ");
         for (f, _) in &missing_fields {
-            s += f.display(sema.db, edition).to_string().as_ref();
+            s += f.display(sema.db, display_target).to_string().as_ref();
             s += ", ";
         }
         // get rid of trailing comma
@@ -479,41 +486,44 @@ pub(super) fn definition(
     subst_types: Option<&Vec<(Symbol, Type)>>,
     config: &HoverConfig,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Markup {
     let mod_path = definition_path(db, &def, edition);
     let label = match def {
-        Definition::Trait(trait_) => {
-            trait_.display_limited(db, config.max_trait_assoc_items_count, edition).to_string()
-        }
+        Definition::Trait(trait_) => trait_
+            .display_limited(db, config.max_trait_assoc_items_count, display_target)
+            .to_string(),
         Definition::Adt(adt @ (Adt::Struct(_) | Adt::Union(_))) => {
-            adt.display_limited(db, config.max_fields_count, edition).to_string()
+            adt.display_limited(db, config.max_fields_count, display_target).to_string()
         }
         Definition::Variant(variant) => {
-            variant.display_limited(db, config.max_fields_count, edition).to_string()
+            variant.display_limited(db, config.max_fields_count, display_target).to_string()
         }
         Definition::Adt(adt @ Adt::Enum(_)) => {
-            adt.display_limited(db, config.max_enum_variants_count, edition).to_string()
+            adt.display_limited(db, config.max_enum_variants_count, display_target).to_string()
         }
         Definition::SelfType(impl_def) => {
             let self_ty = &impl_def.self_ty(db);
             match self_ty.as_adt() {
-                Some(adt) => adt.display_limited(db, config.max_fields_count, edition).to_string(),
-                None => self_ty.display(db, edition).to_string(),
+                Some(adt) => {
+                    adt.display_limited(db, config.max_fields_count, display_target).to_string()
+                }
+                None => self_ty.display(db, display_target).to_string(),
             }
         }
         Definition::Macro(it) => {
-            let mut label = it.display(db, edition).to_string();
+            let mut label = it.display(db, display_target).to_string();
             if let Some(macro_arm) = macro_arm {
                 format_to!(label, " // matched arm #{}", macro_arm);
             }
             label
         }
         Definition::Function(fn_) => {
-            fn_.display_with_container_bounds(db, true, edition).to_string()
+            fn_.display_with_container_bounds(db, true, display_target).to_string()
         }
-        _ => def.label(db, edition),
+        _ => def.label(db, display_target),
     };
-    let docs = def.docs(db, famous_defs, edition);
+    let docs = def.docs(db, famous_defs, display_target);
     let value = || match def {
         Definition::Variant(it) => {
             if !it.parent_enum(db).is_data_carrying(db) {
@@ -525,7 +535,10 @@ pub(super) fn definition(
                         let res = it.value(db).map(|it| format!("{it:?}"));
                         if env::var_os("RA_DEV").is_some() {
                             let res = res.as_deref().unwrap_or("");
-                            Some(format!("{res} ({})", render_const_eval_error(db, err, edition)))
+                            Some(format!(
+                                "{res} ({})",
+                                render_const_eval_error(db, err, display_target)
+                            ))
                         } else {
                             res
                         }
@@ -541,9 +554,12 @@ pub(super) fn definition(
                 Ok(it) => match it.render_debug(db) {
                     Ok(it) => it,
                     Err(err) => {
-                        let it = it.render(db, edition);
+                        let it = it.render(db, display_target);
                         if env::var_os("RA_DEV").is_some() {
-                            format!("{it}\n{}", render_const_eval_error(db, err.into(), edition))
+                            format!(
+                                "{it}\n{}",
+                                render_const_eval_error(db, err.into(), display_target)
+                            )
                         } else {
                             it
                         }
@@ -557,7 +573,7 @@ pub(super) fn definition(
                         body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into());
                     }
                     if env::var_os("RA_DEV").is_some() {
-                        format!("{body}\n{}", render_const_eval_error(db, err, edition))
+                        format!("{body}\n{}", render_const_eval_error(db, err, display_target))
                     } else {
                         body.to_string()
                     }
@@ -570,9 +586,12 @@ pub(super) fn definition(
                 Ok(it) => match it.render_debug(db) {
                     Ok(it) => it,
                     Err(err) => {
-                        let it = it.render(db, edition);
+                        let it = it.render(db, display_target);
                         if env::var_os("RA_DEV").is_some() {
-                            format!("{it}\n{}", render_const_eval_error(db, err.into(), edition))
+                            format!(
+                                "{it}\n{}",
+                                render_const_eval_error(db, err.into(), display_target)
+                            )
                         } else {
                             it
                         }
@@ -586,7 +605,7 @@ pub(super) fn definition(
                         body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into());
                     }
                     if env::var_os("RA_DEV").is_some() {
-                        format!("{body}\n{}", render_const_eval_error(db, err, edition))
+                        format!("{body}\n{}", render_const_eval_error(db, err, display_target))
                     } else {
                         body.to_string()
                     }
@@ -728,7 +747,9 @@ pub(super) fn definition(
 
     let mut extra = String::new();
     if hovered_definition {
-        if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) {
+        if let Some(notable_traits) =
+            render_notable_trait(db, notable_traits, edition, display_target)
+        {
             extra.push_str("\n___\n");
             extra.push_str(&notable_traits);
         }
@@ -772,7 +793,7 @@ pub(super) fn definition(
                         .format_with(", ", |(name, ty), fmt| {
                             fmt(&format_args!(
                                 "`{name}` = `{}`",
-                                ty.display_truncated(db, limit, edition)
+                                ty.display_truncated(db, limit, display_target)
                             ))
                         })
                         .to_string()
@@ -799,7 +820,7 @@ struct DropInfo {
 pub(super) fn literal(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
-    edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<Markup> {
     let lit = token.parent().and_then(ast::Literal::cast)?;
     let ty = if let Some(p) = lit.syntax().parent().and_then(ast::Pat::cast) {
@@ -847,7 +868,7 @@ pub(super) fn literal(
             _ => return None
         }
     };
-    let ty = ty.display(sema.db, edition);
+    let ty = ty.display(sema.db, display_target);
 
     let mut s = format!("```rust\n{ty}\n```\n___\n\n");
     match value {
@@ -879,6 +900,7 @@ fn render_notable_trait(
     db: &RootDatabase,
     notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<String> {
     let mut desc = String::new();
     let mut needs_impl_header = true;
@@ -898,7 +920,7 @@ fn render_notable_trait(
                     f(&name.display(db, edition))?;
                     f(&" = ")?;
                     match ty {
-                        Some(ty) => f(&ty.display(db, edition)),
+                        Some(ty) => f(&ty.display(db, display_target)),
                         None => f(&"?"),
                     }
                 })
@@ -914,8 +936,9 @@ fn type_info(
     config: &HoverConfig,
     ty: TypeInfo,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
-    if let Some(res) = closure_ty(sema, config, &ty, edition) {
+    if let Some(res) = closure_ty(sema, config, &ty, edition, display_target) {
         return Some(res);
     };
     let db = sema.db;
@@ -951,7 +974,7 @@ fn type_info(
                             f(&name.display(db, edition))?;
                             f(&" = ")?;
                             match ty {
-                                Some(ty) => f(&ty.display(db, edition)),
+                                Some(ty) => f(&ty.display(db, display_target)),
                                 None => f(&"?"),
                             }
                         })
@@ -965,8 +988,8 @@ fn type_info(
             desc
         };
 
-        let original = original.display(db, edition).to_string();
-        let adjusted = adjusted_ty.display(db, edition).to_string();
+        let original = original.display(db, display_target).to_string();
+        let adjusted = adjusted_ty.display(db, display_target).to_string();
         let static_text_diff_len = "Coerced to: ".len() - "Type: ".len();
         format!(
             "```text\nType: {:>apad$}\nCoerced to: {:>opad$}\n{notable}```\n",
@@ -977,8 +1000,10 @@ fn type_info(
         )
         .into()
     } else {
-        let mut desc = format!("```rust\n{}\n```", original.display(db, edition));
-        if let Some(extra) = render_notable_trait(db, &notable_traits(db, &original), edition) {
+        let mut desc = format!("```rust\n{}\n```", original.display(db, display_target));
+        if let Some(extra) =
+            render_notable_trait(db, &notable_traits(db, &original), edition, display_target)
+        {
             desc.push_str("\n___\n");
             desc.push_str(&extra);
         };
@@ -995,6 +1020,7 @@ fn closure_ty(
     config: &HoverConfig,
     TypeInfo { original, adjusted }: &TypeInfo,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<HoverResult> {
     let c = original.as_closure()?;
     let mut captures_rendered = c.captured_items(sema.db)
@@ -1027,12 +1053,14 @@ fn closure_ty(
         walk_and_push_ty(sema.db, adjusted_ty, &mut push_new_def);
         format!(
             "\nCoerced to: {}",
-            adjusted_ty.display(sema.db, edition).with_closure_style(hir::ClosureStyle::ImplFn)
+            adjusted_ty
+                .display(sema.db, display_target)
+                .with_closure_style(hir::ClosureStyle::ImplFn)
         )
     } else {
         String::new()
     };
-    let mut markup = format!("```rust\n{}\n```", c.display_with_impl(sema.db, edition));
+    let mut markup = format!("```rust\n{}\n```", c.display_with_impl(sema.db, display_target));
 
     if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
         push_new_def(hir::Trait::from(trait_).into())
@@ -1213,6 +1241,7 @@ fn keyword_hints(
     token: &SyntaxToken,
     parent: syntax::SyntaxNode,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> KeywordHint {
     match token.kind() {
         T![await] | T![loop] | T![match] | T![unsafe] | T![as] | T![try] | T![if] | T![else] => {
@@ -1230,7 +1259,8 @@ fn keyword_hints(
                     walk_and_push_ty(sema.db, &ty.original, &mut push_new_def);
 
                     let ty = ty.adjusted();
-                    let description = format!("{}: {}", token.text(), ty.display(sema.db, edition));
+                    let description =
+                        format!("{}: {}", token.text(), ty.display(sema.db, display_target));
 
                     KeywordHint {
                         description,
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 63039b1cd34..6babdff52a2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -5,14 +5,14 @@ use std::{
 
 use either::Either;
 use hir::{
-    sym, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef,
-    ModuleDefId, Semantics,
+    sym, ClosureStyle, DisplayTarget, HasVisibility, HirDisplay, HirDisplayError, HirWrite,
+    ModuleDef, ModuleDefId, Semantics,
 };
 use ide_db::{famous_defs::FamousDefs, FileRange, RootDatabase};
 use ide_db::{text_edit::TextEdit, FxHashSet};
 use itertools::Itertools;
 use smallvec::{smallvec, SmallVec};
-use span::{Edition, EditionedFileId};
+use span::EditionedFileId;
 use stdx::never;
 use syntax::{
     ast::{self, AstNode, HasGenericParams},
@@ -207,7 +207,8 @@ fn hints(
     file_id: EditionedFileId,
     node: SyntaxNode,
 ) {
-    closing_brace::hints(hints, sema, config, file_id, node.clone());
+    let display_target = sema.first_crate_or_default(file_id.file_id()).to_display_target(sema.db);
+    closing_brace::hints(hints, sema, config, file_id, display_target, node.clone());
     if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
         generic_param::hints(hints, famous_defs, config, any_has_generic_args);
     }
@@ -215,8 +216,8 @@ fn hints(
     match_ast! {
         match node {
             ast::Expr(expr) => {
-                chaining::hints(hints, famous_defs, config, file_id, &expr);
-                adjustment::hints(hints, famous_defs, config, file_id, &expr);
+                chaining::hints(hints, famous_defs, config, display_target, &expr);
+                adjustment::hints(hints, famous_defs, config, display_target, &expr);
                 match expr {
                     ast::Expr::CallExpr(it) => param_name::hints(hints, famous_defs, config, file_id, ast::Expr::from(it)),
                     ast::Expr::MethodCallExpr(it) => {
@@ -224,7 +225,7 @@ fn hints(
                     }
                     ast::Expr::ClosureExpr(it) => {
                         closure_captures::hints(hints, famous_defs, config, file_id, it.clone());
-                        closure_ret::hints(hints, famous_defs, config, file_id, it)
+                        closure_ret::hints(hints, famous_defs, config, display_target, it)
                     },
                     ast::Expr::RangeExpr(it) => range_exclusive::hints(hints, famous_defs, config, file_id,  it),
                     _ => Some(()),
@@ -234,7 +235,7 @@ fn hints(
                 binding_mode::hints(hints, famous_defs, config, file_id,  &it);
                 match it {
                     ast::Pat::IdentPat(it) => {
-                        bind_pat::hints(hints, famous_defs, config, file_id, &it);
+                        bind_pat::hints(hints, famous_defs, config, display_target, &it);
                     }
                     ast::Pat::RangePat(it) => {
                         range_exclusive::hints(hints, famous_defs, config, file_id, it);
@@ -704,7 +705,7 @@ fn label_of_ty(
     famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
     ty: &hir::Type,
-    edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<InlayHintLabel> {
     fn rec(
         sema: &Semantics<'_, RootDatabase>,
@@ -713,7 +714,7 @@ fn label_of_ty(
         ty: &hir::Type,
         label_builder: &mut InlayHintLabelBuilder<'_>,
         config: &InlayHintsConfig,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) -> Result<(), HirDisplayError> {
         let iter_item_type = hint_iterator(sema, famous_defs, ty);
         match iter_item_type {
@@ -744,12 +745,12 @@ fn label_of_ty(
                 label_builder.write_str(LABEL_ITEM)?;
                 label_builder.end_location_link();
                 label_builder.write_str(LABEL_MIDDLE2)?;
-                rec(sema, famous_defs, max_length, &ty, label_builder, config, edition)?;
+                rec(sema, famous_defs, max_length, &ty, label_builder, config, display_target)?;
                 label_builder.write_str(LABEL_END)?;
                 Ok(())
             }
             None => ty
-                .display_truncated(sema.db, max_length, edition)
+                .display_truncated(sema.db, max_length, display_target)
                 .with_closure_style(config.closure_style)
                 .write_to(label_builder),
         }
@@ -762,7 +763,8 @@ fn label_of_ty(
         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 _ =
+        rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config, display_target);
     let r = label_builder.finish();
     Some(r)
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
index 8522ef0a6d5..91b81872952 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
@@ -7,12 +7,12 @@ use std::ops::Not;
 
 use either::Either;
 use hir::{
-    Adjust, Adjustment, AutoBorrow, HirDisplay, Mutability, OverloadedDeref, PointerCast, Safety,
+    Adjust, Adjustment, AutoBorrow, DisplayTarget, HirDisplay, Mutability, OverloadedDeref,
+    PointerCast, Safety,
 };
 use ide_db::famous_defs::FamousDefs;
 
 use ide_db::text_edit::TextEditBuilder;
-use span::EditionedFileId;
 use syntax::ast::{self, prec::ExprPrecedence, AstNode};
 
 use crate::{
@@ -24,7 +24,7 @@ pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
     FamousDefs(sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
-    file_id: EditionedFileId,
+    display_target: DisplayTarget,
     expr: &ast::Expr,
 ) -> Option<()> {
     if config.adjustment_hints_hide_outside_unsafe && !sema.is_inside_unsafe(expr) {
@@ -163,8 +163,8 @@ pub(super) fn hints(
             tooltip: Some(config.lazy_tooltip(|| {
                 InlayTooltip::Markdown(format!(
                     "`{}` → `{}` ({coercion} coercion)",
-                    source.display(sema.db, file_id.edition()),
-                    target.display(sema.db, file_id.edition()),
+                    source.display(sema.db, display_target),
+                    target.display(sema.db, display_target),
                 ))
             })),
         };
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 c2986a9aa66..4379153acaa 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
@@ -3,11 +3,10 @@
 //! fn f(a: i32, b: i32) -> i32 { a + b }
 //! let _x /* i32 */= f(4, 4);
 //! ```
-use hir::Semantics;
+use hir::{DisplayTarget, Semantics};
 use ide_db::{famous_defs::FamousDefs, RootDatabase};
 
 use itertools::Itertools;
-use span::EditionedFileId;
 use syntax::{
     ast::{self, AstNode, HasGenericArgs, HasName},
     match_ast,
@@ -22,7 +21,7 @@ pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
     famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
-    file_id: EditionedFileId,
+    display_target: DisplayTarget,
     pat: &ast::IdentPat,
 ) -> Option<()> {
     if !config.type_hints {
@@ -70,7 +69,7 @@ pub(super) fn hints(
         return None;
     }
 
-    let mut label = label_of_ty(famous_defs, config, &ty, file_id.edition())?;
+    let mut label = label_of_ty(famous_defs, config, &ty, display_target)?;
 
     if config.hide_named_constructor_hints
         && is_named_constructor(sema, pat, &label.to_string()).is_some()
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 8471547727f..604719bc366 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
@@ -1,6 +1,6 @@
 //! Implementation of "chaining" inlay hints.
+use hir::DisplayTarget;
 use ide_db::famous_defs::FamousDefs;
-use span::EditionedFileId;
 use syntax::{
     ast::{self, AstNode},
     Direction, NodeOrToken, SyntaxKind, T,
@@ -14,7 +14,7 @@ pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
     famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
-    file_id: EditionedFileId,
+    display_target: DisplayTarget,
     expr: &ast::Expr,
 ) -> Option<()> {
     if !config.chaining_hints {
@@ -58,7 +58,7 @@ pub(super) fn hints(
                     }
                 }
             }
-            let label = label_of_ty(famous_defs, config, &ty, file_id.edition())?;
+            let label = label_of_ty(famous_defs, config, &ty, display_target)?;
             acc.push(InlayHint {
                 range: expr.syntax().text_range(),
                 kind: InlayKind::Chaining,
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 3767d34e2c7..bec6d38ee9c 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
@@ -3,7 +3,7 @@
 //! fn g() {
 //! } /* fn g */
 //! ```
-use hir::{HirDisplay, Semantics};
+use hir::{DisplayTarget, HirDisplay, Semantics};
 use ide_db::{FileRange, RootDatabase};
 use span::EditionedFileId;
 use syntax::{
@@ -21,6 +21,7 @@ pub(super) fn hints(
     sema: &Semantics<'_, RootDatabase>,
     config: &InlayHintsConfig,
     file_id: EditionedFileId,
+    display_target: DisplayTarget,
     original_node: SyntaxNode,
 ) -> Option<()> {
     let min_lines = config.closing_brace_hints_min_lines?;
@@ -43,9 +44,9 @@ pub(super) fn hints(
                         Some(tr) => format!(
                             "impl {} for {}",
                             tr.name(sema.db).display(sema.db, file_id.edition()),
-                            ty.display_truncated(sema.db, config.max_length, file_id.edition(),
+                            ty.display_truncated(sema.db, config.max_length, display_target,
                         )),
-                        None => format!("impl {}", ty.display_truncated(sema.db, config.max_length, file_id.edition())),
+                        None => format!("impl {}", ty.display_truncated(sema.db, config.max_length, display_target)),
                     };
                     (hint_text, None)
                 },
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
index 7858b1d90a3..61c9c25fe73 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
@@ -1,8 +1,8 @@
 //! Implementation of "closure return type" inlay hints.
 //!
 //! Tests live in [`bind_pat`][super::bind_pat] module.
+use hir::DisplayTarget;
 use ide_db::famous_defs::FamousDefs;
-use span::EditionedFileId;
 use syntax::ast::{self, AstNode};
 
 use crate::{
@@ -14,7 +14,7 @@ pub(super) fn hints(
     acc: &mut Vec<InlayHint>,
     famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
     config: &InlayHintsConfig,
-    file_id: EditionedFileId,
+    display_target: DisplayTarget,
     closure: ast::ClosureExpr,
 ) -> Option<()> {
     if config.closure_return_type_hints == ClosureReturnTypeHints::Never {
@@ -43,7 +43,7 @@ pub(super) fn hints(
         return None;
     }
 
-    let mut label = label_of_ty(famous_defs, config, &ty, file_id.edition())?;
+    let mut label = label_of_ty(famous_defs, config, &ty, display_target)?;
 
     if arrow.is_none() {
         label.prepend_str(" -> ");
diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret.rs b/src/tools/rust-analyzer/crates/ide/src/interpret.rs
index ae11072e34b..74dad488b4d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/interpret.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/interpret.rs
@@ -1,6 +1,5 @@
-use hir::{ConstEvalError, DefWithBody, Semantics};
+use hir::{ConstEvalError, DefWithBody, DisplayTarget, Semantics};
 use ide_db::{base_db::SourceRootDatabase, FilePosition, LineIndexDatabase, RootDatabase};
-use span::Edition;
 use std::time::{Duration, Instant};
 use stdx::format_to;
 use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange};
@@ -46,15 +45,15 @@ fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Dura
             None => format!("file://{path} range {text_range:?}"),
         }
     };
-    let edition = def.module(db).krate().edition(db);
+    let display_target = def.module(db).krate().to_display_target(db);
     let start_time = Instant::now();
     let res = match def {
         DefWithBody::Function(it) => it.eval(db, span_formatter),
-        DefWithBody::Static(it) => it.eval(db).map(|it| it.render(db, edition)),
-        DefWithBody::Const(it) => it.eval(db).map(|it| it.render(db, edition)),
+        DefWithBody::Static(it) => it.eval(db).map(|it| it.render(db, display_target)),
+        DefWithBody::Const(it) => it.eval(db).map(|it| it.render(db, display_target)),
         _ => unreachable!(),
     };
-    let res = res.unwrap_or_else(|e| render_const_eval_error(db, e, edition));
+    let res = res.unwrap_or_else(|e| render_const_eval_error(db, e, display_target));
     let duration = Instant::now() - start_time;
     Some((duration, res))
 }
@@ -62,7 +61,7 @@ fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Dura
 pub(crate) fn render_const_eval_error(
     db: &RootDatabase,
     e: ConstEvalError,
-    edition: Edition,
+    display_target: DisplayTarget,
 ) -> String {
     let span_formatter = |file_id, text_range: TextRange| {
         let path = &db
@@ -76,6 +75,6 @@ pub(crate) fn render_const_eval_error(
         }
     };
     let mut r = String::new();
-    _ = e.pretty_print(&mut r, db, span_formatter, edition);
+    _ = e.pretty_print(&mut r, db, span_formatter, display_target);
     r
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 25d12a4c0b4..5754b4fa82f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -11,7 +11,6 @@ use ide_db::{
     FilePosition, RootDatabase,
 };
 use itertools::Itertools;
-use span::Edition;
 use syntax::{AstNode, SyntaxKind::*, T};
 
 use crate::{doc_links::token_as_doc_comment, parent_module::crates_for, RangeInfo};
@@ -305,13 +304,13 @@ fn def_to_non_local_moniker(
                 if let Some(trait_ref) = impl_.trait_ref(db) {
                     // Trait impls use the trait type for the 2nd parameter.
                     reverse_description.push(MonikerDescriptor {
-                        name: display(db, edition, module, trait_ref),
+                        name: display(db, module, trait_ref),
                         desc: MonikerDescriptorKind::TypeParameter,
                     });
                 }
                 // Both inherent and trait impls use the self type for the first parameter.
                 reverse_description.push(MonikerDescriptor {
-                    name: display(db, edition, module, impl_.self_ty(db)),
+                    name: display(db, module, impl_.self_ty(db)),
                     desc: MonikerDescriptorKind::TypeParameter,
                 });
                 reverse_description.push(MonikerDescriptor {
@@ -390,17 +389,12 @@ fn def_to_non_local_moniker(
     })
 }
 
-fn display<T: HirDisplay>(
-    db: &RootDatabase,
-    edition: Edition,
-    module: hir::Module,
-    it: T,
-) -> String {
+fn display<T: HirDisplay>(db: &RootDatabase, module: hir::Module, it: T) -> String {
     match it.display_source_code(db, module.into(), true) {
         Ok(result) => result,
         // Fallback on display variant that always succeeds
         Err(_) => {
-            let fallback_result = it.display(db, edition).to_string();
+            let fallback_result = it.display(db, module.krate().to_display_target(db)).to_string();
             tracing::error!(
                 display = %fallback_result, "`display_source_code` failed; falling back to using display"
             );
diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
index d9f80cb53dd..d67aaac06fb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
@@ -6,7 +6,7 @@ use arrayvec::ArrayVec;
 use either::Either;
 use hir::{
     db::ExpandDatabase, symbols::FileSymbol, AssocItem, FieldSource, HasContainer, HasCrate,
-    HasSource, HirDisplay, HirFileId, HirFileIdExt, InFile, LocalSource, ModuleSource,
+    HasSource, HirDisplay, HirFileId, InFile, LocalSource, ModuleSource,
 };
 use ide_db::{
     defs::Definition,
@@ -116,7 +116,9 @@ impl NavigationTarget {
                             SymbolKind::Module,
                         );
                         res.docs = module.docs(db);
-                        res.description = Some(module.display(db, edition).to_string());
+                        res.description = Some(
+                            module.display(db, module.krate().to_display_target(db)).to_string(),
+                        );
                         res
                     },
                 )
@@ -183,6 +185,7 @@ impl TryToNav for FileSymbol {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
         let edition =
             self.def.module(db).map(|it| it.krate().edition(db)).unwrap_or(Edition::CURRENT);
+        let display_target = self.def.krate(db).to_display_target(db);
         Some(
             orig_range_with_focus_r(
                 db,
@@ -203,16 +206,34 @@ impl TryToNav for FileSymbol {
                     focus_range,
                     container_name: self.container_name.clone(),
                     description: match self.def {
-                        hir::ModuleDef::Module(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::Function(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::Adt(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::Variant(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::Const(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::Static(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::Trait(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::TraitAlias(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::TypeAlias(it) => Some(it.display(db, edition).to_string()),
-                        hir::ModuleDef::Macro(it) => Some(it.display(db, edition).to_string()),
+                        hir::ModuleDef::Module(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::Function(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::Adt(it) => Some(it.display(db, display_target).to_string()),
+                        hir::ModuleDef::Variant(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::Const(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::Static(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::Trait(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::TraitAlias(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::TypeAlias(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
+                        hir::ModuleDef::Macro(it) => {
+                            Some(it.display(db, display_target).to_string())
+                        }
                         hir::ModuleDef::BuiltinType(_) => None,
                     },
                     docs: None,
@@ -353,12 +374,11 @@ impl ToNavFromAst for hir::TraitAlias {
 
 impl<D> TryToNav for D
 where
-    D: HasSource + ToNavFromAst + Copy + HasDocs + HirDisplay,
+    D: HasSource + ToNavFromAst + Copy + HasDocs + HirDisplay + HasCrate,
     D::Ast: ast::HasName,
 {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
         let src = self.source(db)?;
-        let edition = src.file_id.original_file(db).edition();
         Some(
             NavigationTarget::from_named(
                 db,
@@ -367,7 +387,8 @@ where
             )
             .map(|mut res| {
                 res.docs = self.docs(db);
-                res.description = Some(self.display(db, edition).to_string());
+                res.description =
+                    Some(self.display(db, self.krate(db).to_display_target(db)).to_string());
                 res.container_name = self.container_name(db);
                 res
             }),
@@ -439,7 +460,8 @@ impl TryToNav for hir::ExternCrateDecl {
         let focus = value
             .rename()
             .map_or_else(|| value.name_ref().map(Either::Left), |it| it.name().map(Either::Right));
-        let edition = self.module(db).krate().edition(db);
+        let krate = self.module(db).krate();
+        let edition = krate.edition(db);
 
         Some(orig_range_with_focus(db, file_id, value.syntax(), focus).map(
             |(FileRange { file_id, range: full_range }, focus_range)| {
@@ -455,7 +477,7 @@ impl TryToNav for hir::ExternCrateDecl {
                 );
 
                 res.docs = self.docs(db);
-                res.description = Some(self.display(db, edition).to_string());
+                res.description = Some(self.display(db, krate.to_display_target(db)).to_string());
                 res.container_name = container_name(db, *self, edition);
                 res
             },
@@ -466,14 +488,15 @@ impl TryToNav for hir::ExternCrateDecl {
 impl TryToNav for hir::Field {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
         let src = self.source(db)?;
-        let edition = self.parent_def(db).module(db).krate().edition(db);
+        let krate = self.parent_def(db).module(db).krate();
 
         let field_source = match &src.value {
             FieldSource::Named(it) => {
                 NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field).map(
                     |mut res| {
                         res.docs = self.docs(db);
-                        res.description = Some(self.display(db, edition).to_string());
+                        res.description =
+                            Some(self.display(db, krate.to_display_target(db)).to_string());
                         res
                     },
                 )
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index 509ae3204c3..b8deed01fb7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -9,6 +9,7 @@ use hir::{
 };
 use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn};
 use ide_db::{
+    base_db::SourceDatabase,
     defs::Definition,
     documentation::docs_from_attrs,
     helpers::visit_file_defs,
@@ -399,7 +400,8 @@ pub(crate) fn runnable_impl(
     sema: &Semantics<'_, RootDatabase>,
     def: &hir::Impl,
 ) -> Option<Runnable> {
-    let edition = def.module(sema.db).krate().edition(sema.db);
+    let display_target = def.module(sema.db).krate().to_display_target(sema.db);
+    let edition = display_target.edition;
     let attrs = def.attrs(sema.db);
     if !has_runnable_doc_test(&attrs) {
         return None;
@@ -408,7 +410,7 @@ pub(crate) fn runnable_impl(
     let nav = def.try_to_nav(sema.db)?.call_site();
     let ty = def.self_ty(sema.db);
     let adt_name = ty.as_adt()?.name(sema.db);
-    let mut ty_args = ty.generic_parameters(sema.db, edition).peekable();
+    let mut ty_args = ty.generic_parameters(sema.db, display_target).peekable();
     let params = if ty_args.peek().is_some() {
         format!("<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)))
     } else {
@@ -494,7 +496,11 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
         Definition::SelfType(it) => it.attrs(db),
         _ => return None,
     };
-    let edition = def.krate(db).map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
+    let krate = def.krate(db);
+    let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
+    let display_target = krate
+        .unwrap_or_else(|| (*db.crate_graph().crates_in_topological_order().last().unwrap()).into())
+        .to_display_target(db);
     if !has_runnable_doc_test(&attrs) {
         return None;
     }
@@ -509,7 +515,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
             if let Some(ty) = assoc_item.implementing_ty(db) {
                 if let Some(adt) = ty.as_adt() {
                     let name = adt.name(db);
-                    let mut ty_args = ty.generic_parameters(db, edition).peekable();
+                    let mut ty_args = ty.generic_parameters(db, display_target).peekable();
                     format_to!(path, "{}", name.display(db, edition));
                     if ty_args.peek().is_some() {
                         format_to!(path, "<{}>", ty_args.format_with(",", |ty, cb| cb(&ty)));
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index f9972116004..b5468a5aee9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -4,7 +4,9 @@
 use std::collections::BTreeSet;
 
 use either::Either;
-use hir::{AssocItem, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait};
+use hir::{
+    AssocItem, DisplayTarget, GenericParam, HirDisplay, ModuleDef, PathResolution, Semantics, Trait,
+};
 use ide_db::{
     active_parameter::{callable_for_node, generic_def_for_node},
     documentation::{Documentation, HasDocs},
@@ -82,6 +84,7 @@ pub(crate) fn signature_help(
     let token = sema.descend_into_macros_single_exact(token);
     let edition =
         sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
+    let display_target = sema.first_crate_or_default(file_id).to_display_target(db);
 
     for node in token.parent_ancestors() {
         match_ast! {
@@ -91,49 +94,49 @@ pub(crate) fn signature_help(
                     if cursor_outside {
                         continue;
                     }
-                    return signature_help_for_call(&sema, arg_list, token, edition);
+                    return signature_help_for_call(&sema, arg_list, token, edition, display_target);
                 },
                 ast::GenericArgList(garg_list) => {
                     let cursor_outside = garg_list.r_angle_token().as_ref() == Some(&token);
                     if cursor_outside {
                         continue;
                     }
-                    return signature_help_for_generics(&sema, garg_list, token, edition);
+                    return signature_help_for_generics(&sema, garg_list, token, edition, display_target);
                 },
                 ast::RecordExpr(record) => {
                     let cursor_outside = record.record_expr_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token);
                     if cursor_outside {
                         continue;
                     }
-                    return signature_help_for_record_lit(&sema, record, token, edition);
+                    return signature_help_for_record_lit(&sema, record, token, edition, display_target);
                 },
                 ast::RecordPat(record) => {
                     let cursor_outside = record.record_pat_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token);
                     if cursor_outside {
                         continue;
                     }
-                    return signature_help_for_record_pat(&sema, record, token, edition);
+                    return signature_help_for_record_pat(&sema, record, token, edition, display_target);
                 },
                 ast::TupleStructPat(tuple_pat) => {
                     let cursor_outside = tuple_pat.r_paren_token().as_ref() == Some(&token);
                     if cursor_outside {
                         continue;
                     }
-                    return signature_help_for_tuple_struct_pat(&sema, tuple_pat, token, edition);
+                    return signature_help_for_tuple_struct_pat(&sema, tuple_pat, token, edition, display_target);
                 },
                 ast::TuplePat(tuple_pat) => {
                     let cursor_outside = tuple_pat.r_paren_token().as_ref() == Some(&token);
                     if cursor_outside {
                         continue;
                     }
-                    return signature_help_for_tuple_pat(&sema, tuple_pat, token, edition);
+                    return signature_help_for_tuple_pat(&sema, tuple_pat, token, display_target);
                 },
                 ast::TupleExpr(tuple_expr) => {
                     let cursor_outside = tuple_expr.r_paren_token().as_ref() == Some(&token);
                     if cursor_outside {
                         continue;
                     }
-                    return signature_help_for_tuple_expr(&sema, tuple_expr, token, edition);
+                    return signature_help_for_tuple_expr(&sema, tuple_expr, token, display_target);
                 },
                 _ => (),
             }
@@ -158,6 +161,7 @@ fn signature_help_for_call(
     arg_list: ast::ArgList,
     token: SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     // Find the calling expression and its NameRef
     let mut nodes = arg_list.syntax().ancestors().skip(1);
@@ -221,7 +225,7 @@ fn signature_help_for_call(
     res.signature.push('(');
     {
         if let Some((self_param, _)) = callable.receiver_param(db) {
-            format_to!(res.signature, "{}", self_param.display(db, edition))
+            format_to!(res.signature, "{}", self_param.display(db, display_target))
         }
         let mut buf = String::new();
         for (idx, p) in callable.params().into_iter().enumerate() {
@@ -242,9 +246,9 @@ fn signature_help_for_call(
             // (see FIXME in tests::impl_trait) and falling back on any unknowns.
             match (p.ty().contains_unknown(), fn_params.as_deref()) {
                 (true, Some(fn_params)) => {
-                    format_to!(buf, "{}", fn_params[idx].ty().display(db, edition))
+                    format_to!(buf, "{}", fn_params[idx].ty().display(db, display_target))
                 }
-                _ => format_to!(buf, "{}", p.ty().display(db, edition)),
+                _ => format_to!(buf, "{}", p.ty().display(db, display_target)),
             }
             res.push_call_param(&buf);
         }
@@ -253,7 +257,7 @@ fn signature_help_for_call(
 
     let mut render = |ret_type: hir::Type| {
         if !ret_type.is_unit() {
-            format_to!(res.signature, " -> {}", ret_type.display(db, edition));
+            format_to!(res.signature, " -> {}", ret_type.display(db, display_target));
         }
     };
     match callable.kind() {
@@ -274,6 +278,7 @@ fn signature_help_for_generics(
     arg_list: ast::GenericArgList,
     token: SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     let (generics_def, mut active_parameter, first_arg_is_non_lifetime, variant) =
         generic_def_for_node(sema, &arg_list, &token)?;
@@ -345,7 +350,7 @@ fn signature_help_for_generics(
         }
 
         buf.clear();
-        format_to!(buf, "{}", param.display(db, edition));
+        format_to!(buf, "{}", param.display(db, display_target));
         res.push_generic_param(&buf);
     }
     if let hir::GenericDef::Trait(tr) = generics_def {
@@ -400,6 +405,7 @@ fn signature_help_for_record_lit(
     record: ast::RecordExpr,
     token: SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     signature_help_for_record_(
         sema,
@@ -412,6 +418,7 @@ fn signature_help_for_record_lit(
             .map(|(field, _, ty)| (field, ty)),
         token,
         edition,
+        display_target,
     )
 }
 
@@ -420,6 +427,7 @@ fn signature_help_for_record_pat(
     record: ast::RecordPat,
     token: SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     signature_help_for_record_(
         sema,
@@ -431,6 +439,7 @@ fn signature_help_for_record_pat(
             .filter_map(|field| sema.resolve_record_pat_field(&field)),
         token,
         edition,
+        display_target,
     )
 }
 
@@ -439,6 +448,7 @@ fn signature_help_for_tuple_struct_pat(
     pat: ast::TupleStructPat,
     token: SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     let path = pat.path()?;
     let path_res = sema.resolve_path(&path)?;
@@ -484,7 +494,7 @@ fn signature_help_for_tuple_struct_pat(
         token,
         pat.fields(),
         fields.into_iter().map(|it| it.ty(db)),
-        edition,
+        display_target,
     ))
 }
 
@@ -492,7 +502,7 @@ fn signature_help_for_tuple_pat(
     sema: &Semantics<'_, RootDatabase>,
     pat: ast::TuplePat,
     token: SyntaxToken,
-    edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     let db = sema.db;
     let field_pats = pat.fields();
@@ -512,7 +522,7 @@ fn signature_help_for_tuple_pat(
         token,
         field_pats,
         fields.into_iter(),
-        edition,
+        display_target,
     ))
 }
 
@@ -520,7 +530,7 @@ fn signature_help_for_tuple_expr(
     sema: &Semantics<'_, RootDatabase>,
     expr: ast::TupleExpr,
     token: SyntaxToken,
-    edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     let active_parameter = Some(
         expr.syntax()
@@ -542,7 +552,7 @@ fn signature_help_for_tuple_expr(
     let fields = expr.original.tuple_fields(db);
     let mut buf = String::new();
     for ty in fields {
-        format_to!(buf, "{}", ty.display_truncated(db, Some(20), edition));
+        format_to!(buf, "{}", ty.display_truncated(db, Some(20), display_target));
         res.push_call_param(&buf);
         buf.clear();
     }
@@ -557,6 +567,7 @@ fn signature_help_for_record_(
     fields2: impl Iterator<Item = (hir::Field, hir::Type)>,
     token: SyntaxToken,
     edition: Edition,
+    display_target: DisplayTarget,
 ) -> Option<SignatureHelp> {
     let active_parameter = field_list_children
         .filter_map(NodeOrToken::into_token)
@@ -617,7 +628,7 @@ fn signature_help_for_record_(
             buf,
             "{}: {}",
             name.display(db, edition),
-            ty.display_truncated(db, Some(20), edition)
+            ty.display_truncated(db, Some(20), display_target)
         );
         res.push_record_field(&buf);
         buf.clear();
@@ -632,7 +643,7 @@ fn signature_help_for_record_(
             buf,
             "{}: {}",
             name.display(db, edition),
-            field.ty(db).display_truncated(db, Some(20), edition)
+            field.ty(db).display_truncated(db, Some(20), display_target)
         );
         res.push_record_field(&buf);
         buf.clear();
@@ -648,7 +659,7 @@ fn signature_help_for_tuple_pat_ish(
     token: SyntaxToken,
     mut field_pats: AstChildren<ast::Pat>,
     fields: impl ExactSizeIterator<Item = hir::Type>,
-    edition: Edition,
+    display_target: DisplayTarget,
 ) -> SignatureHelp {
     let rest_pat = field_pats.find(|it| matches!(it, ast::Pat::RestPat(_)));
     let is_left_of_rest_pat =
@@ -675,7 +686,7 @@ fn signature_help_for_tuple_pat_ish(
 
     let mut buf = String::new();
     for ty in fields {
-        format_to!(buf, "{}", ty.display_truncated(db, Some(20), edition));
+        format_to!(buf, "{}", ty.display_truncated(db, Some(20), display_target));
         res.push_call_param(&buf);
         buf.clear();
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index 41957bad7e0..332aecf1e3c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -3,7 +3,7 @@
 
 use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics};
 use ide_db::{
-    base_db::{SourceRootDatabase, VfsPath},
+    base_db::{SourceDatabase, SourceRootDatabase, VfsPath},
     defs::Definition,
     documentation::Documentation,
     famous_defs::FamousDefs,
@@ -118,7 +118,11 @@ fn documentation_for_definition(
     def.docs(
         sema.db,
         famous_defs.as_ref(),
-        def.krate(sema.db).map(|it| it.edition(sema.db)).unwrap_or(Edition::CURRENT),
+        def.krate(sema.db)
+            .unwrap_or_else(|| {
+                (*sema.db.crate_graph().crates_in_topological_order().last().unwrap()).into()
+            })
+            .to_display_target(sema.db),
     )
 }
 
@@ -173,6 +177,7 @@ impl StaticIndex<'_> {
         let root = sema.parse_guess_edition(file_id).syntax().clone();
         let edition =
             sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
+        let display_target = sema.first_crate_or_default(file_id).to_display_target(self.db);
         let tokens = root.descendants_with_tokens().filter_map(|it| match it {
             syntax::NodeOrToken::Node(_) => None,
             syntax::NodeOrToken::Token(it) => Some(it),
@@ -213,6 +218,7 @@ impl StaticIndex<'_> {
                         false,
                         &hover_config,
                         edition,
+                        display_target,
                     )),
                     definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| {
                         FileRange { file_id: it.file_id, range: it.focus_or_full_range() }
@@ -222,7 +228,7 @@ impl StaticIndex<'_> {
                     display_name: def
                         .name(self.db)
                         .map(|name| name.display(self.db, edition).to_string()),
-                    signature: Some(def.label(self.db, edition)),
+                    signature: Some(def.label(self.db, display_target)),
                     kind: def_to_kind(self.db, def),
                 });
                 self.def_map.insert(def, it);
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
index edb83bc4eac..34bca7bce12 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
@@ -1,12 +1,11 @@
 use std::fmt;
 
-use hir::{Field, HirDisplay, Layout, Semantics, Type};
+use hir::{DisplayTarget, Field, HirDisplay, Layout, Semantics, Type};
 use ide_db::{
     defs::Definition,
     helpers::{get_definition, pick_best_token},
     RootDatabase,
 };
-use span::Edition;
 use syntax::{AstNode, SyntaxKind};
 
 use crate::FilePosition;
@@ -84,10 +83,7 @@ pub(crate) fn view_memory_layout(
 ) -> Option<RecursiveMemoryLayout> {
     let sema = Semantics::new(db);
     let file = sema.parse_guess_edition(position.file_id);
-    let edition = sema
-        .attach_first_edition(position.file_id)
-        .map(|it| it.edition())
-        .unwrap_or(Edition::CURRENT);
+    let display_target = sema.first_crate_or_default(position.file_id).to_display_target(db);
     let token =
         pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
             SyntaxKind::IDENT => 3,
@@ -114,7 +110,7 @@ pub(crate) fn view_memory_layout(
         ty: &Type,
         layout: &Layout,
         parent_idx: usize,
-        edition: Edition,
+        display_target: DisplayTarget,
     ) {
         let mut fields = ty
             .fields(db)
@@ -145,7 +141,7 @@ pub(crate) fn view_memory_layout(
             if let Ok(child_layout) = child_ty.layout(db) {
                 nodes.push(MemoryLayoutNode {
                     item_name: field.name(db),
-                    typename: child_ty.display(db, edition).to_string(),
+                    typename: child_ty.display(db, display_target).to_string(),
                     size: child_layout.size(),
                     alignment: child_layout.align(),
                     offset: match *field {
@@ -161,7 +157,7 @@ pub(crate) fn view_memory_layout(
                     item_name: field.name(db)
                         + format!("(no layout data: {:?})", child_ty.layout(db).unwrap_err())
                             .as_ref(),
-                    typename: child_ty.display(db, edition).to_string(),
+                    typename: child_ty.display(db, display_target).to_string(),
                     size: 0,
                     offset: 0,
                     alignment: 0,
@@ -174,7 +170,7 @@ pub(crate) fn view_memory_layout(
 
         for (i, (_, child_ty)) in fields.iter().enumerate() {
             if let Ok(child_layout) = child_ty.layout(db) {
-                read_layout(nodes, db, child_ty, &child_layout, children_start + i, edition);
+                read_layout(nodes, db, child_ty, &child_layout, children_start + i, display_target);
             }
         }
     }
@@ -192,7 +188,7 @@ pub(crate) fn view_memory_layout(
                 def => def.name(db).map(|n| n.as_str().to_owned()).unwrap_or("[ROOT]".to_owned()),
             };
 
-            let typename = ty.display(db, edition).to_string();
+            let typename = ty.display(db, display_target).to_string();
 
             let mut nodes = vec![MemoryLayoutNode {
                 item_name,
@@ -204,7 +200,7 @@ pub(crate) fn view_memory_layout(
                 children_start: -1,
                 children_len: 0,
             }];
-            read_layout(&mut nodes, db, &ty, &layout, 0, edition);
+            read_layout(&mut nodes, db, &ty, &layout, 0, display_target);
 
             RecursiveMemoryLayout { nodes }
         })
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 b9e4457fc98..dee76ee15c3 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
@@ -390,6 +390,8 @@ impl flags::AnalysisStats {
 
         for &file_id in &file_ids {
             let sema = hir::Semantics::new(db);
+            let display_target =
+                sema.first_crate_or_default(file_id.file_id()).to_display_target(db);
 
             let parse = sema.parse_guess_edition(file_id.into());
             let file_txt = db.file_text(file_id.into());
@@ -467,7 +469,7 @@ impl flags::AnalysisStats {
                                 prefer_absolute: false,
                                 allow_unstable: true,
                             },
-                            Edition::LATEST,
+                            display_target,
                         )
                         .unwrap();
                     syntax_hit_found |= trim(&original_text) == trim(&generated);
@@ -641,6 +643,7 @@ impl flags::AnalysisStats {
         for &body_id in bodies {
             let name = body_id.name(db).unwrap_or_else(Name::missing);
             let module = body_id.module(db);
+            let display_target = module.krate().to_display_target(db);
             let full_name = move || {
                 module
                     .krate()
@@ -739,12 +742,12 @@ impl flags::AnalysisStats {
                             start.col,
                             end.line + 1,
                             end.col,
-                            ty.display(db, Edition::LATEST)
+                            ty.display(db, display_target)
                         ));
                     } else {
                         bar.println(format!(
                             "unknown location: {}",
-                            ty.display(db, Edition::LATEST)
+                            ty.display(db, display_target)
                         ));
                     }
                 }
@@ -752,7 +755,7 @@ impl flags::AnalysisStats {
                     println!(
                         r#"{},type,"{}""#,
                         location_csv_expr(db, vfs, &sm(), expr_id),
-                        ty.display(db, Edition::LATEST)
+                        ty.display(db, display_target)
                     );
                 }
                 if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
@@ -767,15 +770,15 @@ impl flags::AnalysisStats {
                                 start.col,
                                 end.line + 1,
                                 end.col,
-                                mismatch.expected.display(db, Edition::LATEST),
-                                mismatch.actual.display(db, Edition::LATEST)
+                                mismatch.expected.display(db, display_target),
+                                mismatch.actual.display(db, display_target)
                             ));
                         } else {
                             bar.println(format!(
                                 "{}: Expected {}, got {}",
                                 name.display(db, Edition::LATEST),
-                                mismatch.expected.display(db, Edition::LATEST),
-                                mismatch.actual.display(db, Edition::LATEST)
+                                mismatch.expected.display(db, display_target),
+                                mismatch.actual.display(db, display_target)
                             ));
                         }
                     }
@@ -783,8 +786,8 @@ impl flags::AnalysisStats {
                         println!(
                             r#"{},mismatch,"{}","{}""#,
                             location_csv_expr(db, vfs, &sm(), expr_id),
-                            mismatch.expected.display(db, Edition::LATEST),
-                            mismatch.actual.display(db, Edition::LATEST)
+                            mismatch.expected.display(db, display_target),
+                            mismatch.actual.display(db, display_target)
                         );
                     }
                 }
@@ -843,12 +846,12 @@ impl flags::AnalysisStats {
                             start.col,
                             end.line + 1,
                             end.col,
-                            ty.display(db, Edition::LATEST)
+                            ty.display(db, display_target)
                         ));
                     } else {
                         bar.println(format!(
                             "unknown location: {}",
-                            ty.display(db, Edition::LATEST)
+                            ty.display(db, display_target)
                         ));
                     }
                 }
@@ -856,7 +859,7 @@ impl flags::AnalysisStats {
                     println!(
                         r#"{},type,"{}""#,
                         location_csv_pat(db, vfs, &sm(), pat_id),
-                        ty.display(db, Edition::LATEST)
+                        ty.display(db, display_target)
                     );
                 }
                 if let Some(mismatch) = inference_result.type_mismatch_for_pat(pat_id) {
@@ -870,15 +873,15 @@ impl flags::AnalysisStats {
                                 start.col,
                                 end.line + 1,
                                 end.col,
-                                mismatch.expected.display(db, Edition::LATEST),
-                                mismatch.actual.display(db, Edition::LATEST)
+                                mismatch.expected.display(db, display_target),
+                                mismatch.actual.display(db, display_target)
                             ));
                         } else {
                             bar.println(format!(
                                 "{}: Expected {}, got {}",
                                 name.display(db, Edition::LATEST),
-                                mismatch.expected.display(db, Edition::LATEST),
-                                mismatch.actual.display(db, Edition::LATEST)
+                                mismatch.expected.display(db, display_target),
+                                mismatch.actual.display(db, display_target)
                             ));
                         }
                     }
@@ -886,8 +889,8 @@ impl flags::AnalysisStats {
                         println!(
                             r#"{},mismatch,"{}","{}""#,
                             location_csv_pat(db, vfs, &sm(), pat_id),
-                            mismatch.expected.display(db, Edition::LATEST),
-                            mismatch.actual.display(db, Edition::LATEST)
+                            mismatch.expected.display(db, display_target),
+                            mismatch.actual.display(db, display_target)
                         );
                     }
                 }