Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #19330 from ChayimFriedman2/normalize-projection
fix: Normalize projections in evaluated const display and layout calculation
Lukas Wirth 2025-03-10
parent cf255a6 · parent 422213c · commit 27a5b1b
-rw-r--r--crates/hir-ty/src/consteval.rs17
-rw-r--r--crates/hir-ty/src/consteval/tests.rs18
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs15
-rw-r--r--crates/hir-ty/src/display.rs107
-rw-r--r--crates/hir-ty/src/layout.rs3
-rw-r--r--crates/hir-ty/src/lib.rs10
-rw-r--r--crates/hir-ty/src/mir.rs4
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs6
-rw-r--r--crates/hir-ty/src/mir/eval.rs27
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs4
-rw-r--r--crates/hir-ty/src/mir/eval/tests.rs5
-rw-r--r--crates/hir-ty/src/mir/lower.rs55
-rw-r--r--crates/hir-ty/src/mir/lower/pattern_matching.rs7
-rw-r--r--crates/hir-ty/src/mir/pretty.rs63
-rw-r--r--crates/hir-ty/src/tests.rs47
-rw-r--r--crates/hir-ty/src/tests/closure_captures.rs8
-rw-r--r--crates/hir/src/lib.rs71
-rw-r--r--crates/hir/src/semantics.rs8
-rw-r--r--crates/hir/src/symbols.rs14
-rw-r--r--crates/hir/src/term_search/expr.rs50
-rw-r--r--crates/ide-assists/src/handlers/generate_function.rs11
-rw-r--r--crates/ide-assists/src/handlers/generate_getter_or_setter.rs2
-rw-r--r--crates/ide-assists/src/handlers/inline_const_as_literal.rs2
-rw-r--r--crates/ide-assists/src/handlers/term_search.rs9
-rw-r--r--crates/ide-assists/src/utils.rs44
-rw-r--r--crates/ide-completion/src/context.rs7
-rw-r--r--crates/ide-completion/src/context/tests.rs2
-rw-r--r--crates/ide-completion/src/render.rs13
-rw-r--r--crates/ide-completion/src/render/const_.rs2
-rw-r--r--crates/ide-completion/src/render/function.rs32
-rw-r--r--crates/ide-completion/src/render/literal.rs4
-rw-r--r--crates/ide-completion/src/render/macro_.rs2
-rw-r--r--crates/ide-completion/src/render/type_alias.rs2
-rw-r--r--crates/ide-completion/src/render/union_literal.rs2
-rw-r--r--crates/ide-completion/src/render/variant.rs22
-rw-r--r--crates/ide-db/src/defs.rs93
-rw-r--r--crates/ide-db/src/path_transform.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/expected_function.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/invalid_cast.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/type_mismatch.rs8
-rw-r--r--crates/ide-diagnostics/src/handlers/typed_hole.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_field.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/unresolved_method.rs4
-rw-r--r--crates/ide-diagnostics/src/lib.rs19
-rw-r--r--crates/ide-ssr/src/matching.rs20
-rw-r--r--crates/ide/src/hover.rs54
-rw-r--r--crates/ide/src/hover/render.rs124
-rw-r--r--crates/ide/src/hover/tests.rs39
-rw-r--r--crates/ide/src/inlay_hints.rs28
-rw-r--r--crates/ide/src/inlay_hints/adjustment.rs10
-rw-r--r--crates/ide/src/inlay_hints/bind_pat.rs7
-rw-r--r--crates/ide/src/inlay_hints/chaining.rs6
-rw-r--r--crates/ide/src/inlay_hints/closing_brace.rs7
-rw-r--r--crates/ide/src/inlay_hints/closure_ret.rs6
-rw-r--r--crates/ide/src/interpret.rs15
-rw-r--r--crates/ide/src/moniker.rs14
-rw-r--r--crates/ide/src/navigation_target.rs61
-rw-r--r--crates/ide/src/runnables.rs14
-rw-r--r--crates/ide/src/signature_help.rs55
-rw-r--r--crates/ide/src/static_index.rs12
-rw-r--r--crates/ide/src/view_memory_layout.rs20
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs41
64 files changed, 869 insertions, 503 deletions
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 7839589994..fb604569f4 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/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/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index 249170c4f3..26a3b70229 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/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/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 59aaf85164..cc6f4d9e52 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/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/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 6ee4780d20..95ce36390d 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -45,6 +45,7 @@ use crate::{
db::{HirDatabase, InternedClosure},
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
generics::generics,
+ infer::normalize,
layout::Layout,
lt_from_placeholder_idx,
mapping::from_chalk,
@@ -87,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,
}
@@ -164,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>
@@ -171,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 {
@@ -181,6 +184,7 @@ pub trait HirDisplay {
limited_size,
omit_verbose_types,
display_target,
+ display_kind,
closure_style,
show_container_bounds,
}
@@ -191,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,
@@ -203,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,
}
}
@@ -214,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,
@@ -226,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,
}
}
@@ -237,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,
@@ -249,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,
}
}
@@ -272,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(),
}) {
@@ -284,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,
{
@@ -295,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,
}
}
@@ -306,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,
@@ -318,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>(
@@ -394,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 { .. })
}
@@ -450,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,
}
@@ -479,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,
@@ -533,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;
@@ -653,10 +680,8 @@ fn render_const_scalar(
memory_map: &MemoryMap,
ty: &Ty,
) -> Result<(), HirDisplayError> {
- // FIXME: We need to get krate from the final callers of the hir display
- // infrastructure and have it here as a field on `f`.
- let trait_env =
- TraitEnvironment::empty(*f.db.crate_graph().crates_in_topological_order().last().unwrap());
+ let trait_env = TraitEnvironment::empty(f.krate());
+ let ty = normalize(f.db, trait_env.clone(), ty.clone());
match ty.kind(Interner) {
TyKind::Scalar(s) => match s {
Scalar::Bool => write!(f, "{}", b[0] != 0),
@@ -1109,7 +1134,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);
@@ -1198,8 +1223,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(),
@@ -1207,7 +1232,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()),
@@ -1246,7 +1271,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();
@@ -1275,7 +1300,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,
));
@@ -1344,8 +1369,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,
));
@@ -1465,7 +1490,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,
));
@@ -1508,7 +1533,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}}")?;
@@ -1516,7 +1541,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,
));
@@ -1573,7 +1598,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())
@@ -1958,7 +1983,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/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index a4e49e0aa1..6b5c712159 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -435,6 +435,9 @@ pub fn layout_of_ty_query(
TyKind::Error => return Err(LayoutError::HasErrorType),
TyKind::AssociatedType(id, subst) => {
// Try again with `TyKind::Alias` to normalize the associated type.
+ // Usually we should not try to normalize `TyKind::AssociatedType`, but layout calculation is used
+ // in monomorphized MIR where this is okay. If outside monomorphization, this will lead to cycle,
+ // which we will recover from with an error.
let ty = TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy {
associated_ty_id: *id,
substitution: subst.clone(),
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 707c437772..2f9245a332 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/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/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index 41304bbd8a..56c431ef8d 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/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/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index 9c86d3b59f..fbcca388e7 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/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/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index d0f9f4519c..74a34e2981 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/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/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 7d3376f56b..f61ecabb7e 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/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/crates/hir-ty/src/mir/eval/tests.rs b/crates/hir-ty/src/mir/eval/tests.rs
index 2b5486fc5f..084c391d26 100644
--- a/crates/hir-ty/src/mir/eval/tests.rs
+++ b/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/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 2fe4ce8319..520717e799 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/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/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 289175feef..783f92b204 100644
--- a/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/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/crates/hir-ty/src/mir/pretty.rs b/crates/hir-ty/src/mir/pretty.rs
index 2a26101ac4..7d7d4106cb 100644
--- a/crates/hir-ty/src/mir/pretty.rs
+++ b/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/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index f5a4d4ff35..81e38be228 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/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/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs
index 34d299edd1..6f7bfc4ea7 100644
--- a/crates/hir-ty/src/tests/closure_captures.rs
+++ b/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/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index cb667767d7..a807550947 100644
--- a/crates/hir/src/lib.rs
+++ b/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},
@@ -148,7 +148,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,
@@ -283,6 +283,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)]
@@ -471,6 +486,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 {
@@ -1866,7 +1892,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:?}"),
}
}
@@ -2452,8 +2478,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),
@@ -2464,7 +2488,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
}
};
@@ -2728,8 +2757,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> {
@@ -4198,9 +4227,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)
}
}
@@ -4508,18 +4541,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()
}
@@ -5324,7 +5357,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()
@@ -5334,10 +5367,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)))
}
})
}
@@ -5346,7 +5379,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()
@@ -5356,7 +5389,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/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index b0c2feaac1..5e2eebcd13 100644
--- a/crates/hir/src/semantics.rs
+++ b/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/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 2ebd88edae..81eb6a70ad 100644
--- a/crates/hir/src/symbols.rs
+++ b/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/crates/hir/src/term_search/expr.rs b/crates/hir/src/term_search/expr.rs
index d2070f0e18..0d672dc332 100644
--- a/crates/hir/src/term_search/expr.rs
+++ b/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/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index 91e248a1de..7af2a2e1e6 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/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/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
index ac58af6252..1b16ba5fc8 100644
--- a/crates/ide-assists/src/handlers/generate_getter_or_setter.rs
+++ b/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/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/crates/ide-assists/src/handlers/inline_const_as_literal.rs
index 139078eee7..ca5882d031 100644
--- a/crates/ide-assists/src/handlers/inline_const_as_literal.rs
+++ b/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/crates/ide-assists/src/handlers/term_search.rs b/crates/ide-assists/src/handlers/term_search.rs
index 66671c934c..e10897b3be 100644
--- a/crates/ide-assists/src/handlers/term_search.rs
+++ b/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/crates/ide-assists/src/utils.rs b/crates/ide-assists/src/utils.rs
index 39686f065a..a6fa170671 100644
--- a/crates/ide-assists/src/utils.rs
+++ b/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/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 919b30f7f9..e686a29309 100644
--- a/crates/ide-completion/src/context.rs
+++ b/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/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs
index fc2bfc01e6..a03f632cdf 100644
--- a/crates/ide-completion/src/context/tests.rs
+++ b/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/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 4d0a4a4782..c82905edde 100644
--- a/crates/ide-completion/src/render.rs
+++ b/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/crates/ide-completion/src/render/const_.rs b/crates/ide-completion/src/render/const_.rs
index e357ab24d2..f11b302367 100644
--- a/crates/ide-completion/src/render/const_.rs
+++ b/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/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index fd90613964..4693bdc047 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/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/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index 9e2bb8db54..ffda52fb47 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/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/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs
index e265e92f97..8b2476d153 100644
--- a/crates/ide-completion/src/render/macro_.rs
+++ b/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/crates/ide-completion/src/render/type_alias.rs b/crates/ide-completion/src/render/type_alias.rs
index 1b952f3136..d57feee4fa 100644
--- a/crates/ide-completion/src/render/type_alias.rs
+++ b/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/crates/ide-completion/src/render/union_literal.rs b/crates/ide-completion/src/render/union_literal.rs
index 7420362652..09154e81c0 100644
--- a/crates/ide-completion/src/render/union_literal.rs
+++ b/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/crates/ide-completion/src/render/variant.rs b/crates/ide-completion/src/render/variant.rs
index d8516ea107..83718e5722 100644
--- a/crates/ide-completion/src/render/variant.rs
+++ b/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/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 6f71c3d9bd..502314ed1e 100644
--- a/crates/ide-db/src/defs.rs
+++ b/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/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs
index 126b30470b..a348a4ef7d 100644
--- a/crates/ide-db/src/path_transform.rs
+++ b/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/crates/ide-diagnostics/src/handlers/expected_function.rs b/crates/ide-diagnostics/src/handlers/expected_function.rs
index e3a1e12e02..af25c2b2e3 100644
--- a/crates/ide-diagnostics/src/handlers/expected_function.rs
+++ b/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/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/crates/ide-diagnostics/src/handlers/invalid_cast.rs
index 5730508436..82cd1f2fde 100644
--- a/crates/ide-diagnostics/src/handlers/invalid_cast.rs
+++ b/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/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
index a9ff06fb0a..7d0f10983d 100644
--- a/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
+++ b/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/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
index 1363a8ff0d..3db2e013a3 100644
--- a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
+++ b/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/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 7cf8282d05..c726a3bcd3 100644
--- a/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/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/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs
index b023a95fb3..c25318eda4 100644
--- a/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/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/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/crates/ide-diagnostics/src/handlers/unresolved_field.rs
index dfb03eee73..6ab713a589 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_field.rs
+++ b/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/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index e4de107249..35e7521af7 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/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/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 0a55b6e9be..e15d349578 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/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/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs
index 4bead14e31..e219ba4bf6 100644
--- a/crates/ide-ssr/src/matching.rs
+++ b/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/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 9a3e77f3a9..b00de6ba40 100644
--- a/crates/ide/src/hover.rs
+++ b/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/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index c5a83e58ce..31ef89a07c 100644
--- a/crates/ide/src/hover/render.rs
+++ b/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/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 7c720d97cb..6b470d921f 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -10947,3 +10947,42 @@ pub struct ManuallyDrop$0<T: ?Sized> {
"#]],
);
}
+
+#[test]
+fn projection_const() {
+ // This uses two crates, which have *no* relation between them, to test another thing:
+ // `render_const_scalar()` used to just use the last crate for the trait env, which will
+ // fail in this scenario.
+ check(
+ r#"
+//- /foo.rs crate:foo
+pub trait PublicFlags {
+ type Internal;
+}
+
+pub struct NoteDialects(<NoteDialects as PublicFlags>::Internal);
+
+impl NoteDialects {
+ pub const CLAP$0: Self = Self(InternalBitFlags);
+}
+
+pub struct InternalBitFlags;
+
+impl PublicFlags for NoteDialects {
+ type Internal = InternalBitFlags;
+}
+//- /bar.rs crate:bar
+ "#,
+ expect![[r#"
+ *CLAP*
+
+ ```rust
+ foo::NoteDialects
+ ```
+
+ ```rust
+ pub const CLAP: Self = NoteDialects(InternalBitFlags)
+ ```
+ "#]],
+ );
+}
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 63039b1cd3..6babdff52a 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/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/crates/ide/src/inlay_hints/adjustment.rs b/crates/ide/src/inlay_hints/adjustment.rs
index 8522ef0a6d..91b8187295 100644
--- a/crates/ide/src/inlay_hints/adjustment.rs
+++ b/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/crates/ide/src/inlay_hints/bind_pat.rs b/crates/ide/src/inlay_hints/bind_pat.rs
index c2986a9aa6..4379153aca 100644
--- a/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/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/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs
index 8471547727..604719bc36 100644
--- a/crates/ide/src/inlay_hints/chaining.rs
+++ b/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/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs
index 3767d34e2c..bec6d38ee9 100644
--- a/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/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/crates/ide/src/inlay_hints/closure_ret.rs b/crates/ide/src/inlay_hints/closure_ret.rs
index 7858b1d90a..61c9c25fe7 100644
--- a/crates/ide/src/inlay_hints/closure_ret.rs
+++ b/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/crates/ide/src/interpret.rs b/crates/ide/src/interpret.rs
index ae11072e34..74dad488b4 100644
--- a/crates/ide/src/interpret.rs
+++ b/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/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 25d12a4c0b..5754b4fa82 100644
--- a/crates/ide/src/moniker.rs
+++ b/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/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index d9f80cb53d..d67aaac06f 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/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/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 509ae3204c..b8deed01fb 100644
--- a/crates/ide/src/runnables.rs
+++ b/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/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index f997211600..b5468a5aee 100644
--- a/crates/ide/src/signature_help.rs
+++ b/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/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 41957bad7e..332aecf1e3 100644
--- a/crates/ide/src/static_index.rs
+++ b/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/crates/ide/src/view_memory_layout.rs b/crates/ide/src/view_memory_layout.rs
index edb83bc4ea..34bca7bce1 100644
--- a/crates/ide/src/view_memory_layout.rs
+++ b/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/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index b9e4457fc9..dee76ee15c 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/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)
);
}
}