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