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) ); } }