From 2fc0dc0f13332e5fdc7df9e756318b467251c5d3 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 27 Feb 2025 14:19:54 +0200 Subject: [PATCH] Pass the target crate in `HirFormatter` This is required to format evaluated consts, because we need trait env, and it needs the crate (currently it uses the last crate in topological order, which is wrong, the next commit will fix that). --- crates/hir-ty/src/consteval.rs | 17 ++- crates/hir-ty/src/consteval/tests.rs | 18 ++- crates/hir-ty/src/diagnostics/expr.rs | 15 +- crates/hir-ty/src/display.rs | 136 +++++++++++------- crates/hir-ty/src/lib.rs | 10 +- crates/hir-ty/src/mir.rs | 4 +- crates/hir-ty/src/mir/borrowck.rs | 6 +- crates/hir-ty/src/mir/eval.rs | 27 ++-- crates/hir-ty/src/mir/eval/shim.rs | 4 +- crates/hir-ty/src/mir/eval/tests.rs | 5 +- crates/hir-ty/src/mir/lower.rs | 55 ++++--- .../hir-ty/src/mir/lower/pattern_matching.rs | 7 +- crates/hir-ty/src/mir/pretty.rs | 63 +++++--- crates/hir-ty/src/tests.rs | 47 +++--- crates/hir-ty/src/tests/closure_captures.rs | 8 +- crates/hir/src/lib.rs | 71 ++++++--- crates/hir/src/semantics.rs | 8 ++ crates/hir/src/symbols.rs | 14 +- crates/hir/src/term_search/expr.rs | 50 +++++-- .../src/handlers/generate_function.rs | 11 +- .../src/handlers/generate_getter_or_setter.rs | 2 +- .../src/handlers/inline_const_as_literal.rs | 2 +- .../ide-assists/src/handlers/term_search.rs | 9 +- crates/ide-assists/src/utils.rs | 44 ++++-- crates/ide-completion/src/context.rs | 7 +- crates/ide-completion/src/context/tests.rs | 2 +- crates/ide-completion/src/render.rs | 13 +- crates/ide-completion/src/render/const_.rs | 2 +- crates/ide-completion/src/render/function.rs | 32 ++--- crates/ide-completion/src/render/literal.rs | 4 +- crates/ide-completion/src/render/macro_.rs | 2 +- .../ide-completion/src/render/type_alias.rs | 2 +- .../src/render/union_literal.rs | 2 +- crates/ide-completion/src/render/variant.rs | 22 +-- crates/ide-db/src/defs.rs | 93 +++++++----- crates/ide-db/src/path_transform.rs | 4 +- .../src/handlers/expected_function.rs | 2 +- .../src/handlers/invalid_cast.rs | 2 +- .../src/handlers/moved_out_of_ref.rs | 2 +- .../trait_impl_redundant_assoc_item.rs | 4 +- .../src/handlers/type_mismatch.rs | 8 +- .../src/handlers/typed_hole.rs | 4 +- .../src/handlers/unresolved_field.rs | 2 +- .../src/handlers/unresolved_method.rs | 4 +- crates/ide-diagnostics/src/lib.rs | 19 ++- crates/ide-ssr/src/matching.rs | 20 +-- crates/ide/src/hover.rs | 54 +++++-- crates/ide/src/hover/render.rs | 124 ++++++++++------ crates/ide/src/inlay_hints.rs | 28 ++-- crates/ide/src/inlay_hints/adjustment.rs | 10 +- crates/ide/src/inlay_hints/bind_pat.rs | 7 +- crates/ide/src/inlay_hints/chaining.rs | 6 +- crates/ide/src/inlay_hints/closing_brace.rs | 7 +- crates/ide/src/inlay_hints/closure_ret.rs | 6 +- crates/ide/src/interpret.rs | 15 +- crates/ide/src/moniker.rs | 14 +- crates/ide/src/navigation_target.rs | 61 +++++--- crates/ide/src/runnables.rs | 14 +- crates/ide/src/signature_help.rs | 55 ++++--- crates/ide/src/static_index.rs | 12 +- crates/ide/src/view_memory_layout.rs | 20 ++- .../rust-analyzer/src/cli/analysis_stats.rs | 41 +++--- 62 files changed, 842 insertions(+), 517 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 b3613b372b..41152d9022 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -88,6 +88,7 @@ pub struct HirFormatter<'a> { show_container_bounds: bool, omit_verbose_types: bool, closure_style: ClosureStyle, + display_kind: DisplayKind, display_target: DisplayTarget, bounds_formatting_ctx: BoundsFormattingCtx, } @@ -165,6 +166,7 @@ pub trait HirDisplay { limited_size: Option, omit_verbose_types: bool, display_target: DisplayTarget, + display_kind: DisplayKind, closure_style: ClosureStyle, show_container_bounds: bool, ) -> HirDisplayWrapper<'a, Self> @@ -172,7 +174,7 @@ pub trait HirDisplay { Self: Sized, { assert!( - !matches!(display_target, DisplayTarget::SourceCode { .. }), + !matches!(display_kind, DisplayKind::SourceCode { .. }), "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead" ); HirDisplayWrapper { @@ -182,6 +184,7 @@ pub trait HirDisplay { limited_size, omit_verbose_types, display_target, + display_kind, closure_style, show_container_bounds, } @@ -192,7 +195,7 @@ pub trait HirDisplay { fn display<'a>( &'a self, db: &'a dyn HirDatabase, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -204,7 +207,8 @@ pub trait HirDisplay { limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Diagnostics, show_container_bounds: false, } } @@ -215,7 +219,7 @@ pub trait HirDisplay { &'a self, db: &'a dyn HirDatabase, max_size: Option, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -227,7 +231,8 @@ pub trait HirDisplay { limited_size: None, omit_verbose_types: true, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Diagnostics, show_container_bounds: false, } } @@ -238,7 +243,7 @@ pub trait HirDisplay { &'a self, db: &'a dyn HirDatabase, limited_size: Option, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -250,7 +255,8 @@ pub trait HirDisplay { limited_size, omit_verbose_types: true, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Diagnostics, show_container_bounds: false, } } @@ -273,7 +279,8 @@ pub trait HirDisplay { entity_limit: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::SourceCode { module_id, allow_opaque }, + display_target: DisplayTarget::from_crate(db, module_id.krate()), + display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque }, show_container_bounds: false, bounds_formatting_ctx: Default::default(), }) { @@ -285,29 +292,10 @@ 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> - where - Self: Sized, - { - HirDisplayWrapper { - db, - t: self, - max_size: None, - limited_size: None, - omit_verbose_types: false, - closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Test, - show_container_bounds: false, - } - } - - /// Returns a String representation of `self` that shows the constraint from - /// the container for functions - fn display_with_container_bounds<'a>( + fn display_test<'a>( &'a self, db: &'a dyn HirDatabase, - show_container_bounds: bool, - edition: Edition, + display_target: DisplayTarget, ) -> HirDisplayWrapper<'a, Self> where Self: Sized, @@ -319,21 +307,44 @@ pub trait HirDisplay { limited_size: None, omit_verbose_types: false, closure_style: ClosureStyle::ImplFn, - display_target: DisplayTarget::Diagnostics { edition }, + display_target, + display_kind: DisplayKind::Test, + show_container_bounds: false, + } + } + + /// Returns a String representation of `self` that shows the constraint from + /// the container for functions + fn display_with_container_bounds<'a>( + &'a self, + db: &'a dyn HirDatabase, + show_container_bounds: bool, + display_target: DisplayTarget, + ) -> HirDisplayWrapper<'a, Self> + where + Self: Sized, + { + HirDisplayWrapper { + db, + t: self, + max_size: None, + limited_size: None, + omit_verbose_types: false, + closure_style: ClosureStyle::ImplFn, + 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( @@ -395,20 +406,33 @@ impl HirFormatter<'_> { } } +#[derive(Debug, Clone, Copy)] +pub struct DisplayTarget { + krate: CrateId, + pub edition: Edition, +} + +impl DisplayTarget { + pub fn from_crate(db: &dyn HirDatabase, krate: CrateId) -> Self { + let edition = db.crate_graph()[krate].edition; + Self { krate, edition } + } +} + #[derive(Clone, Copy)] -pub enum DisplayTarget { +pub enum DisplayKind { /// Display types for inlays, doc popups, autocompletion, etc... /// Showing `{unknown}` or not qualifying paths is fine here. /// There's no reason for this to fail. - Diagnostics { edition: Edition }, + Diagnostics, /// Display types for inserting them in source files. /// The generated code should compile, so paths need to be qualified. - SourceCode { module_id: ModuleId, allow_opaque: bool }, + SourceCode { target_module_id: ModuleId, allow_opaque: bool }, /// Only for test purpose to keep real types Test, } -impl DisplayTarget { +impl DisplayKind { fn is_source_code(self) -> bool { matches!(self, Self::SourceCode { .. }) } @@ -451,6 +475,7 @@ pub struct HirDisplayWrapper<'a, T> { limited_size: Option, omit_verbose_types: bool, closure_style: ClosureStyle, + display_kind: DisplayKind, display_target: DisplayTarget, show_container_bounds: bool, } @@ -480,6 +505,7 @@ impl HirDisplayWrapper<'_, T> { max_size: self.max_size, entity_limit: self.limited_size, omit_verbose_types: self.omit_verbose_types, + display_kind: self.display_kind, display_target: self.display_target, closure_style: self.closure_style, show_container_bounds: self.show_container_bounds, @@ -534,7 +560,7 @@ impl HirDisplay for ProjectionTy { // if we are projection on a type parameter, check if the projection target has bounds // itself, if so, we render them directly as `impl Bound` instead of the less useful // `::Assoc` - if !f.display_target.is_source_code() { + if !f.display_kind.is_source_code() { if let TyKind::Placeholder(idx) = self_ty.kind(Interner) { if !f.bounds_formatting_ctx.contains(self) { let db = f.db; @@ -1111,7 +1137,7 @@ impl HirDisplay for Ty { let def = from_chalk(db, *def); let sig = db.callable_item_signature(def).substitute(Interner, parameters); - if f.display_target.is_source_code() { + if f.display_kind.is_source_code() { // `FnDef` is anonymous and there's no surface syntax for it. Show it as a // function pointer type. return sig.hir_fmt(f); @@ -1200,8 +1226,8 @@ impl HirDisplay for Ty { } TyKind::Adt(AdtId(def_id), parameters) => { f.start_location_link((*def_id).into()); - match f.display_target { - DisplayTarget::Diagnostics { .. } | DisplayTarget::Test => { + match f.display_kind { + DisplayKind::Diagnostics { .. } | DisplayKind::Test { .. } => { let name = match *def_id { hir_def::AdtId::StructId(it) => db.struct_data(it).name.clone(), hir_def::AdtId::UnionId(it) => db.union_data(it).name.clone(), @@ -1209,7 +1235,7 @@ impl HirDisplay for Ty { }; write!(f, "{}", name.display(f.db.upcast(), f.edition()))?; } - DisplayTarget::SourceCode { module_id, allow_opaque: _ } => { + DisplayKind::SourceCode { target_module_id: module_id, allow_opaque: _ } => { if let Some(path) = find_path::find_path( db.upcast(), ItemInNs::Types((*def_id).into()), @@ -1248,7 +1274,7 @@ impl HirDisplay for Ty { let type_alias_data = db.type_alias_data(type_alias); // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) - if f.display_target.is_test() { + if f.display_kind.is_test() { f.start_location_link(trait_.into()); write!(f, "{}", trait_data.name.display(f.db.upcast(), f.edition()))?; f.end_location_link(); @@ -1277,7 +1303,7 @@ impl HirDisplay for Ty { f.end_location_link(); } TyKind::OpaqueType(opaque_ty_id, parameters) => { - if !f.display_target.allows_opaque() { + if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::OpaqueType, )); @@ -1346,8 +1372,8 @@ impl HirDisplay for Ty { } } TyKind::Closure(id, substs) => { - if f.display_target.is_source_code() { - if !f.display_target.allows_opaque() { + if f.display_kind.is_source_code() { + if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::OpaqueType, )); @@ -1467,7 +1493,7 @@ impl HirDisplay for Ty { } TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { - if !f.display_target.allows_opaque() { + if !f.display_kind.allows_opaque() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::OpaqueType, )); @@ -1510,7 +1536,7 @@ impl HirDisplay for Ty { }; } TyKind::Error => { - if f.display_target.is_source_code() { + if f.display_kind.is_source_code() { f.write_char('_')?; } else { write!(f, "{{unknown}}")?; @@ -1518,7 +1544,7 @@ impl HirDisplay for Ty { } TyKind::InferenceVar(..) => write!(f, "_")?, TyKind::Coroutine(_, subst) => { - if f.display_target.is_source_code() { + if f.display_kind.is_source_code() { return Err(HirDisplayError::DisplaySourceCodeError( DisplaySourceCodeError::Coroutine, )); @@ -1575,7 +1601,7 @@ fn generic_args_sans_defaults<'ga>( generic_def: Option, parameters: &'ga [GenericArg], ) -> &'ga [GenericArg] { - if f.display_target.is_source_code() || f.omit_verbose_types() { + if f.display_kind.is_source_code() || f.omit_verbose_types() { match generic_def .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) .filter(|it| !it.is_empty()) @@ -1960,7 +1986,7 @@ impl HirDisplay for LifetimeData { write!(f, "{}", param_data.name.display(f.db.upcast(), f.edition()))?; Ok(()) } - _ if f.display_target.is_source_code() => write!(f, "'_"), + _ if f.display_kind.is_source_code() => write!(f, "'_"), LifetimeData::BoundVar(idx) => idx.hir_fmt(f), LifetimeData::InferenceVar(_) => write!(f, "_"), LifetimeData::Static => write!(f, "'static"), diff --git a/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 { 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 ProjectionElem { _ => { 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, + 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(&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 = 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, body: Arc, - body_source_map: Arc| { + body_source_map: Arc, + krate: CrateId| { + let display_target = DisplayTarget::from_crate(&db, krate); let mut types: Vec<(InFile, &Ty)> = Vec::new(); let mut mismatches: Vec<(InFile, &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 = 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 7549d54a54..a59f90b175 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}, @@ -147,7 +147,7 @@ pub use { hir_ty::{ consteval::ConstEvalError, diagnostics::UnsafetyReason, - display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, + display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite}, dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode}, layout::LayoutError, method_resolution::TyFingerprint, @@ -282,6 +282,21 @@ impl Crate { let data = &db.crate_graph()[self.id]; data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone()) } + + pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget { + DisplayTarget::from_crate(db, self.id) + } + + fn core(db: &dyn HirDatabase) -> Option { + let crate_graph = db.crate_graph(); + let result = crate_graph + .iter() + .find(|&krate| { + matches!(crate_graph[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) + }) + .map(Crate::from); + result + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -470,6 +485,17 @@ impl ModuleDef { } } +impl HasCrate for ModuleDef { + fn krate(&self, db: &dyn HirDatabase) -> Crate { + match self.module(db) { + Some(module) => module.krate(), + None => Crate::core(db).unwrap_or_else(|| { + (*db.crate_graph().crates_in_topological_order().last().unwrap()).into() + }), + } + } +} + impl HasVisibility for ModuleDef { fn visibility(&self, db: &dyn HirDatabase) -> Visibility { match *self { @@ -1865,7 +1891,7 @@ impl DefWithBody { pub fn debug_mir(self, db: &dyn HirDatabase) -> String { let body = db.mir_body(self.id()); match body { - Ok(body) => body.pretty_print(db), + Ok(body) => body.pretty_print(db, self.module(db).krate().to_display_target(db)), Err(e) => format!("error:\n{e:?}"), } } @@ -2451,8 +2477,6 @@ impl Function { db: &dyn HirDatabase, span_formatter: impl Fn(FileId, TextRange) -> String, ) -> Result { - let krate = HasModule::krate(&self.id, db.upcast()); - let edition = db.crate_graph()[krate].edition; let body = db.monomorphized_mir_body( self.id.into(), Substitution::empty(Interner), @@ -2463,7 +2487,12 @@ impl Function { Ok(_) => "pass".to_owned(), Err(e) => { let mut r = String::new(); - _ = e.pretty_print(&mut r, db, &span_formatter, edition); + _ = e.pretty_print( + &mut r, + db, + &span_formatter, + self.krate(db).to_display_target(db), + ); r } }; @@ -2727,8 +2756,8 @@ pub struct EvaluatedConst { } impl EvaluatedConst { - pub fn render(&self, db: &dyn HirDatabase, edition: Edition) -> String { - format!("{}", self.const_.display(db, edition)) + pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { + format!("{}", self.const_.display(db, display_target)) } pub fn render_debug(&self, db: &dyn HirDatabase) -> Result { @@ -4197,9 +4226,13 @@ impl ConstParam { Type::new(db, self.id.parent(), db.const_param_ty(self.id)) } - pub fn default(self, db: &dyn HirDatabase, edition: Edition) -> Option { + pub fn default( + self, + db: &dyn HirDatabase, + display_target: DisplayTarget, + ) -> Option { let arg = generic_arg_from_param(db, self.id.into())?; - known_const_to_ast(arg.constant(Interner)?, db, edition) + known_const_to_ast(arg.constant(Interner)?, db, display_target) } } @@ -4507,18 +4540,18 @@ impl Closure { TyKind::Closure(self.id, self.subst).intern(Interner) } - pub fn display_with_id(&self, db: &dyn HirDatabase, edition: Edition) -> String { + pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { self.clone() .as_ty() - .display(db, edition) + .display(db, display_target) .with_closure_style(ClosureStyle::ClosureWithId) .to_string() } - pub fn display_with_impl(&self, db: &dyn HirDatabase, edition: Edition) -> String { + pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { self.clone() .as_ty() - .display(db, edition) + .display(db, display_target) .with_closure_style(ClosureStyle::ImplFn) .to_string() } @@ -5323,7 +5356,7 @@ impl Type { pub fn type_and_const_arguments<'a>( &'a self, db: &'a dyn HirDatabase, - edition: Edition, + display_target: DisplayTarget, ) -> impl Iterator + 'a { self.ty .strip_references() @@ -5333,10 +5366,10 @@ impl Type { .filter_map(move |arg| { // arg can be either a `Ty` or `constant` if let Some(ty) = arg.ty(Interner) { - Some(format_smolstr!("{}", ty.display(db, edition))) + Some(format_smolstr!("{}", ty.display(db, display_target))) } else { arg.constant(Interner) - .map(|const_| format_smolstr!("{}", const_.display(db, edition))) + .map(|const_| format_smolstr!("{}", const_.display(db, display_target))) } }) } @@ -5345,7 +5378,7 @@ impl Type { pub fn generic_parameters<'a>( &'a self, db: &'a dyn HirDatabase, - edition: Edition, + display_target: DisplayTarget, ) -> impl Iterator + 'a { // iterate the lifetime self.as_adt() @@ -5355,7 +5388,7 @@ impl Type { }) .into_iter() // add the type and const parameters - .chain(self.type_and_const_arguments(db, edition)) + .chain(self.type_and_const_arguments(db, display_target)) } pub fn iterate_method_candidates_with_traits( diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 1b8531209c..034e727d31 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 { 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, work: Vec, current_container_name: Option, - 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 { 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::, 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::, 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::, 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::, 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::, 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 { 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 = generic_params.into_iter().map(|it| it.node.clone_for_update()).collect(); - let where_preds: Vec<_> = + let where_preds: Vec = 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 4f6c4cb663..b32a589a1b 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 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 aab54ca5e0..3429ae1f46 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, 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, 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 { 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>, acc: &mut Vec, ) -> 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 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 = - 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> { 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::>(), @@ -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> { // FIXME: make this work in attributes let expr_or_pat = file @@ -371,16 +394,17 @@ fn hover_ranged( .find_map(Either::::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, edition: Edition, + display_target: DisplayTarget, ) -> Option { 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 { 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 { 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 { 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 { 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 { 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(¬able_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 { 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, Name)>)], edition: Edition, + display_target: DisplayTarget, ) -> Option { 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 { - 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, ¬able_traits(db, &original), edition) { + let mut desc = format!("```rust\n{}\n```", original.display(db, display_target)); + if let Some(extra) = + render_notable_trait(db, ¬able_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 { 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/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 { 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, 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, 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, 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, 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( - db: &RootDatabase, - edition: Edition, - module: hir::Module, - it: T, -) -> String { +fn display(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> { 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 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> { 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> { 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 { - 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 { 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 { 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 { // 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 { 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 { 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 { 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 { 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 { 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 { 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, token: SyntaxToken, edition: Edition, + display_target: DisplayTarget, ) -> Option { 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, fields: impl ExactSizeIterator, - 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 { 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) ); } }